xref: /freebsd-src/contrib/llvm-project/libcxx/include/__format/format_functions.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1bdd1243dSDimitry Andric // -*- C++ -*-
2bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
3bdd1243dSDimitry Andric //
4bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7bdd1243dSDimitry Andric //
8bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
9bdd1243dSDimitry Andric 
10bdd1243dSDimitry Andric #ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS
11bdd1243dSDimitry Andric #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include <__algorithm/clamp.h>
14bdd1243dSDimitry Andric #include <__concepts/convertible_to.h>
15bdd1243dSDimitry Andric #include <__concepts/same_as.h>
16bdd1243dSDimitry Andric #include <__config>
17bdd1243dSDimitry Andric #include <__format/buffer.h>
18bdd1243dSDimitry Andric #include <__format/format_arg.h>
19bdd1243dSDimitry Andric #include <__format/format_arg_store.h>
20bdd1243dSDimitry Andric #include <__format/format_args.h>
21bdd1243dSDimitry Andric #include <__format/format_context.h>
22bdd1243dSDimitry Andric #include <__format/format_error.h>
23bdd1243dSDimitry Andric #include <__format/format_parse_context.h>
24bdd1243dSDimitry Andric #include <__format/format_string.h>
25bdd1243dSDimitry Andric #include <__format/format_to_n_result.h>
26bdd1243dSDimitry Andric #include <__format/formatter.h>
27bdd1243dSDimitry Andric #include <__format/formatter_bool.h>
28bdd1243dSDimitry Andric #include <__format/formatter_char.h>
29bdd1243dSDimitry Andric #include <__format/formatter_floating_point.h>
30bdd1243dSDimitry Andric #include <__format/formatter_integer.h>
31bdd1243dSDimitry Andric #include <__format/formatter_pointer.h>
32bdd1243dSDimitry Andric #include <__format/formatter_string.h>
33bdd1243dSDimitry Andric #include <__format/parser_std_format_spec.h>
34bdd1243dSDimitry Andric #include <__iterator/back_insert_iterator.h>
3506c3fb27SDimitry Andric #include <__iterator/concepts.h>
36bdd1243dSDimitry Andric #include <__iterator/incrementable_traits.h>
3706c3fb27SDimitry Andric #include <__iterator/iterator_traits.h> // iter_value_t
38bdd1243dSDimitry Andric #include <__variant/monostate.h>
39bdd1243dSDimitry Andric #include <array>
40bdd1243dSDimitry Andric #include <string>
41bdd1243dSDimitry Andric #include <string_view>
42bdd1243dSDimitry Andric 
43bdd1243dSDimitry Andric #ifndef _LIBCPP_HAS_NO_LOCALIZATION
44*0fca6ea1SDimitry Andric #  include <__locale>
45bdd1243dSDimitry Andric #endif
46bdd1243dSDimitry Andric 
47bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
48bdd1243dSDimitry Andric #  pragma GCC system_header
49bdd1243dSDimitry Andric #endif
50bdd1243dSDimitry Andric 
51b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS
52b3edf446SDimitry Andric #include <__undef_macros>
53b3edf446SDimitry Andric 
54bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
55bdd1243dSDimitry Andric 
5606c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
57bdd1243dSDimitry Andric 
58bdd1243dSDimitry Andric // TODO FMT Evaluate which templates should be external templates. This
59bdd1243dSDimitry Andric // improves the efficiency of the header. However since the header is still
60bdd1243dSDimitry Andric // under heavy development and not all classes are stable it makes no sense
61bdd1243dSDimitry Andric // to do this optimization now.
62bdd1243dSDimitry Andric 
63bdd1243dSDimitry Andric using format_args = basic_format_args<format_context>;
64bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
65bdd1243dSDimitry Andric using wformat_args = basic_format_args<wformat_context>;
66bdd1243dSDimitry Andric #  endif
67bdd1243dSDimitry Andric 
68bdd1243dSDimitry Andric template <class _Context = format_context, class... _Args>
69*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) {
70*0fca6ea1SDimitry Andric   return std::__format_arg_store<_Context, _Args...>(__args...);
71bdd1243dSDimitry Andric }
72bdd1243dSDimitry Andric 
73bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
74bdd1243dSDimitry Andric template <class... _Args>
75*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&... __args) {
76*0fca6ea1SDimitry Andric   return std::__format_arg_store<wformat_context, _Args...>(__args...);
77bdd1243dSDimitry Andric }
78bdd1243dSDimitry Andric #  endif
79bdd1243dSDimitry Andric 
80bdd1243dSDimitry Andric namespace __format {
81bdd1243dSDimitry Andric 
82bdd1243dSDimitry Andric /// Helper class parse and handle argument.
83bdd1243dSDimitry Andric ///
84bdd1243dSDimitry Andric /// When parsing a handle which is not enabled the code is ill-formed.
85bdd1243dSDimitry Andric /// This helper uses the parser of the appropriate formatter for the stored type.
86bdd1243dSDimitry Andric template <class _CharT>
87bdd1243dSDimitry Andric class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
88bdd1243dSDimitry Andric public:
8906c3fb27SDimitry Andric   template <class _ParseContext>
9006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const {
9106c3fb27SDimitry Andric     __parse_(__ctx);
9206c3fb27SDimitry Andric   }
93bdd1243dSDimitry Andric 
94bdd1243dSDimitry Andric   template <class _Tp>
95bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void __enable() {
9606c3fb27SDimitry Andric     __parse_ = [](basic_format_parse_context<_CharT>& __ctx) {
97bdd1243dSDimitry Andric       formatter<_Tp, _CharT> __f;
9806c3fb27SDimitry Andric       __ctx.advance_to(__f.parse(__ctx));
99bdd1243dSDimitry Andric     };
100bdd1243dSDimitry Andric   }
101bdd1243dSDimitry Andric 
102bdd1243dSDimitry Andric   // Before calling __parse the proper handler needs to be set with __enable.
103bdd1243dSDimitry Andric   // The default handler isn't a core constant expression.
104bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()
105bdd1243dSDimitry Andric       : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {}
106bdd1243dSDimitry Andric 
107bdd1243dSDimitry Andric private:
108bdd1243dSDimitry Andric   void (*__parse_)(basic_format_parse_context<_CharT>&);
109bdd1243dSDimitry Andric };
110bdd1243dSDimitry Andric 
111bdd1243dSDimitry Andric // Dummy format_context only providing the parts used during constant
112bdd1243dSDimitry Andric // validation of the basic_format_string.
113bdd1243dSDimitry Andric template <class _CharT>
114bdd1243dSDimitry Andric struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context {
115bdd1243dSDimitry Andric public:
116bdd1243dSDimitry Andric   using char_type = _CharT;
117bdd1243dSDimitry Andric 
118bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(
119bdd1243dSDimitry Andric       const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)
120bdd1243dSDimitry Andric       : __args_(__args), __handles_(__handles), __size_(__size) {}
121bdd1243dSDimitry Andric 
122bdd1243dSDimitry Andric   // During the compile-time validation nothing needs to be written.
123bdd1243dSDimitry Andric   // Therefore all operations of this iterator are a NOP.
124bdd1243dSDimitry Andric   struct iterator {
125bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }
126bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }
127bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }
128bdd1243dSDimitry Andric   };
129bdd1243dSDimitry Andric 
130bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
131bdd1243dSDimitry Andric     if (__id >= __size_)
13206c3fb27SDimitry Andric       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
133bdd1243dSDimitry Andric     return __args_[__id];
134bdd1243dSDimitry Andric   }
135bdd1243dSDimitry Andric 
136bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {
137bdd1243dSDimitry Andric     if (__id >= __size_)
13806c3fb27SDimitry Andric       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
139bdd1243dSDimitry Andric     return __handles_[__id];
140bdd1243dSDimitry Andric   }
141bdd1243dSDimitry Andric 
142bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }
143bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}
144bdd1243dSDimitry Andric 
145bdd1243dSDimitry Andric private:
146bdd1243dSDimitry Andric   const __arg_t* __args_;
147bdd1243dSDimitry Andric   const __compile_time_handle<_CharT>* __handles_;
148bdd1243dSDimitry Andric   size_t __size_;
149bdd1243dSDimitry Andric };
150bdd1243dSDimitry Andric 
15106c3fb27SDimitry Andric // [format.string.std]/8
15206c3fb27SDimitry Andric // If { arg-idopt } is used in a width or precision, the value of the
15306c3fb27SDimitry Andric // corresponding formatting argument is used in its place. If the
15406c3fb27SDimitry Andric // corresponding formatting argument is not of standard signed or unsigned
15506c3fb27SDimitry Andric // integer type, or its value is negative for precision or non-positive for
15606c3fb27SDimitry Andric // width, an exception of type format_error is thrown.
15706c3fb27SDimitry Andric //
15806c3fb27SDimitry Andric // _HasPrecision does the formatter have a precision?
15906c3fb27SDimitry Andric template <class _CharT, class _Tp, bool _HasPrecision = false>
16006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument(
16106c3fb27SDimitry Andric     basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) {
16206c3fb27SDimitry Andric   auto __validate_type = [](__arg_t __type) {
16306c3fb27SDimitry Andric     // LWG3720 originally allowed "signed or unsigned integer types", however
16406c3fb27SDimitry Andric     // the final version explicitly changed it to "*standard* signed or unsigned
16506c3fb27SDimitry Andric     // integer types". It's trivial to use 128-bit integrals in libc++'s
16606c3fb27SDimitry Andric     // implementation, but other implementations may not implement it.
16706c3fb27SDimitry Andric     // (Using a width or precision, that does not fit in 64-bits, sounds very
16806c3fb27SDimitry Andric     // unlikely in real world code.)
169bdd1243dSDimitry Andric     switch (__type) {
170bdd1243dSDimitry Andric     case __arg_t::__int:
171bdd1243dSDimitry Andric     case __arg_t::__long_long:
172bdd1243dSDimitry Andric     case __arg_t::__unsigned:
173bdd1243dSDimitry Andric     case __arg_t::__unsigned_long_long:
174bdd1243dSDimitry Andric       return;
175bdd1243dSDimitry Andric 
176bdd1243dSDimitry Andric     default:
17706c3fb27SDimitry Andric       std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type");
178bdd1243dSDimitry Andric     }
17906c3fb27SDimitry Andric   };
180bdd1243dSDimitry Andric 
181bdd1243dSDimitry Andric   formatter<_Tp, _CharT> __formatter;
182bdd1243dSDimitry Andric   __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
183bdd1243dSDimitry Andric   if (__formatter.__parser_.__width_as_arg_)
18406c3fb27SDimitry Andric     __validate_type(__ctx.arg(__formatter.__parser_.__width_));
185bdd1243dSDimitry Andric 
186bdd1243dSDimitry Andric   if constexpr (_HasPrecision)
187bdd1243dSDimitry Andric     if (__formatter.__parser_.__precision_as_arg_)
18806c3fb27SDimitry Andric       __validate_type(__ctx.arg(__formatter.__parser_.__precision_));
189bdd1243dSDimitry Andric }
190bdd1243dSDimitry Andric 
191bdd1243dSDimitry Andric // This function is not user facing, so it can directly use the non-standard types of the "variant".
192bdd1243dSDimitry Andric template <class _CharT>
193cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(
194cb14a3feSDimitry Andric     basic_format_parse_context<_CharT>& __parse_ctx,
195bdd1243dSDimitry Andric     __compile_time_basic_format_context<_CharT>& __ctx,
196bdd1243dSDimitry Andric     __arg_t __type) {
197bdd1243dSDimitry Andric   switch (__type) {
198bdd1243dSDimitry Andric   case __arg_t::__none:
199bdd1243dSDimitry Andric     std::__throw_format_error("Invalid argument");
200bdd1243dSDimitry Andric   case __arg_t::__boolean:
201bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);
202bdd1243dSDimitry Andric   case __arg_t::__char_type:
203bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);
204bdd1243dSDimitry Andric   case __arg_t::__int:
205bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);
206bdd1243dSDimitry Andric   case __arg_t::__long_long:
207bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);
208bdd1243dSDimitry Andric   case __arg_t::__i128:
209bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_INT128
210bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);
211bdd1243dSDimitry Andric #  else
212bdd1243dSDimitry Andric     std::__throw_format_error("Invalid argument");
213bdd1243dSDimitry Andric #  endif
214bdd1243dSDimitry Andric     return;
215bdd1243dSDimitry Andric   case __arg_t::__unsigned:
216bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);
217bdd1243dSDimitry Andric   case __arg_t::__unsigned_long_long:
218bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);
219bdd1243dSDimitry Andric   case __arg_t::__u128:
220bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_INT128
221bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);
222bdd1243dSDimitry Andric #  else
223bdd1243dSDimitry Andric     std::__throw_format_error("Invalid argument");
224bdd1243dSDimitry Andric #  endif
225bdd1243dSDimitry Andric     return;
226bdd1243dSDimitry Andric   case __arg_t::__float:
227bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);
228bdd1243dSDimitry Andric   case __arg_t::__double:
229bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);
230bdd1243dSDimitry Andric   case __arg_t::__long_double:
231bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);
232bdd1243dSDimitry Andric   case __arg_t::__const_char_type_ptr:
233bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);
234bdd1243dSDimitry Andric   case __arg_t::__string_view:
235bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);
236bdd1243dSDimitry Andric   case __arg_t::__ptr:
237bdd1243dSDimitry Andric     return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);
238bdd1243dSDimitry Andric   case __arg_t::__handle:
239bdd1243dSDimitry Andric     std::__throw_format_error("Handle should use __compile_time_validate_handle_argument");
240bdd1243dSDimitry Andric   }
241bdd1243dSDimitry Andric   std::__throw_format_error("Invalid argument");
242bdd1243dSDimitry Andric }
243bdd1243dSDimitry Andric 
24406c3fb27SDimitry Andric template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx>
24506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Iterator
246cb14a3feSDimitry Andric __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) {
24706c3fb27SDimitry Andric   using _CharT                        = iter_value_t<_Iterator>;
248bdd1243dSDimitry Andric   __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
249bdd1243dSDimitry Andric 
2508a4dda33SDimitry Andric   if (__r.__last == __end)
2518a4dda33SDimitry Andric     std::__throw_format_error("The argument index should end with a ':' or a '}'");
2528a4dda33SDimitry Andric 
25306c3fb27SDimitry Andric   bool __parse = *__r.__last == _CharT(':');
25406c3fb27SDimitry Andric   switch (*__r.__last) {
255bdd1243dSDimitry Andric   case _CharT(':'):
256bdd1243dSDimitry Andric     // The arg-id has a format-specifier, advance the input to the format-spec.
25706c3fb27SDimitry Andric     __parse_ctx.advance_to(__r.__last + 1);
258bdd1243dSDimitry Andric     break;
259bdd1243dSDimitry Andric   case _CharT('}'):
260bdd1243dSDimitry Andric     // The arg-id has no format-specifier.
26106c3fb27SDimitry Andric     __parse_ctx.advance_to(__r.__last);
262bdd1243dSDimitry Andric     break;
263bdd1243dSDimitry Andric   default:
26406c3fb27SDimitry Andric     std::__throw_format_error("The argument index should end with a ':' or a '}'");
265bdd1243dSDimitry Andric   }
266bdd1243dSDimitry Andric 
267bdd1243dSDimitry Andric   if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
268bdd1243dSDimitry Andric     __arg_t __type = __ctx.arg(__r.__value);
2691ac55f4cSDimitry Andric     if (__type == __arg_t::__none)
27006c3fb27SDimitry Andric       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
2711ac55f4cSDimitry Andric     else if (__type == __arg_t::__handle)
272bdd1243dSDimitry Andric       __ctx.__handle(__r.__value).__parse(__parse_ctx);
2731ac55f4cSDimitry Andric     else if (__parse)
274bdd1243dSDimitry Andric       __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
275bdd1243dSDimitry Andric   } else
2765f757f3fSDimitry Andric     std::__visit_format_arg(
277bdd1243dSDimitry Andric         [&](auto __arg) {
278bdd1243dSDimitry Andric           if constexpr (same_as<decltype(__arg), monostate>)
27906c3fb27SDimitry Andric             std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
280bdd1243dSDimitry Andric           else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
281bdd1243dSDimitry Andric             __arg.format(__parse_ctx, __ctx);
282bdd1243dSDimitry Andric           else {
283bdd1243dSDimitry Andric             formatter<decltype(__arg), _CharT> __formatter;
284bdd1243dSDimitry Andric             if (__parse)
285bdd1243dSDimitry Andric               __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
286bdd1243dSDimitry Andric             __ctx.advance_to(__formatter.format(__arg, __ctx));
287bdd1243dSDimitry Andric           }
288bdd1243dSDimitry Andric         },
289bdd1243dSDimitry Andric         __ctx.arg(__r.__value));
290bdd1243dSDimitry Andric 
291bdd1243dSDimitry Andric   __begin = __parse_ctx.begin();
292bdd1243dSDimitry Andric   if (__begin == __end || *__begin != _CharT('}'))
293bdd1243dSDimitry Andric     std::__throw_format_error("The replacement field misses a terminating '}'");
294bdd1243dSDimitry Andric 
295bdd1243dSDimitry Andric   return ++__begin;
296bdd1243dSDimitry Andric }
297bdd1243dSDimitry Andric 
298bdd1243dSDimitry Andric template <class _ParseCtx, class _Ctx>
299cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
300bdd1243dSDimitry Andric   using _CharT = typename _ParseCtx::char_type;
301bdd1243dSDimitry Andric   static_assert(same_as<typename _Ctx::char_type, _CharT>);
302bdd1243dSDimitry Andric 
30306c3fb27SDimitry Andric   auto __begin                     = __parse_ctx.begin();
30406c3fb27SDimitry Andric   auto __end                       = __parse_ctx.end();
305bdd1243dSDimitry Andric   typename _Ctx::iterator __out_it = __ctx.out();
306bdd1243dSDimitry Andric   while (__begin != __end) {
307bdd1243dSDimitry Andric     switch (*__begin) {
308bdd1243dSDimitry Andric     case _CharT('{'):
309bdd1243dSDimitry Andric       ++__begin;
310bdd1243dSDimitry Andric       if (__begin == __end)
311bdd1243dSDimitry Andric         std::__throw_format_error("The format string terminates at a '{'");
312bdd1243dSDimitry Andric 
313bdd1243dSDimitry Andric       if (*__begin != _CharT('{')) [[likely]] {
3145f757f3fSDimitry Andric         __ctx.advance_to(std::move(__out_it));
315cb14a3feSDimitry Andric         __begin  = __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
316bdd1243dSDimitry Andric         __out_it = __ctx.out();
317bdd1243dSDimitry Andric 
318bdd1243dSDimitry Andric         // The output is written and __begin points to the next character. So
319bdd1243dSDimitry Andric         // start the next iteration.
320bdd1243dSDimitry Andric         continue;
321bdd1243dSDimitry Andric       }
322bdd1243dSDimitry Andric       // The string is an escape character.
323bdd1243dSDimitry Andric       break;
324bdd1243dSDimitry Andric 
325bdd1243dSDimitry Andric     case _CharT('}'):
326bdd1243dSDimitry Andric       ++__begin;
327bdd1243dSDimitry Andric       if (__begin == __end || *__begin != _CharT('}'))
328bdd1243dSDimitry Andric         std::__throw_format_error("The format string contains an invalid escape sequence");
329bdd1243dSDimitry Andric 
330bdd1243dSDimitry Andric       break;
331bdd1243dSDimitry Andric     }
332bdd1243dSDimitry Andric 
333bdd1243dSDimitry Andric     // Copy the character to the output verbatim.
334bdd1243dSDimitry Andric     *__out_it++ = *__begin++;
335bdd1243dSDimitry Andric   }
336bdd1243dSDimitry Andric   return __out_it;
337bdd1243dSDimitry Andric }
338bdd1243dSDimitry Andric 
339bdd1243dSDimitry Andric } // namespace __format
340bdd1243dSDimitry Andric 
3415f757f3fSDimitry Andric #  if _LIBCPP_STD_VER >= 26
3425f757f3fSDimitry Andric template <class _CharT>
3435f757f3fSDimitry Andric struct _LIBCPP_TEMPLATE_VIS __runtime_format_string {
3445f757f3fSDimitry Andric private:
3455f757f3fSDimitry Andric   basic_string_view<_CharT> __str_;
3465f757f3fSDimitry Andric 
3475f757f3fSDimitry Andric   template <class _Cp, class... _Args>
3485f757f3fSDimitry Andric   friend struct _LIBCPP_TEMPLATE_VIS basic_format_string;
3495f757f3fSDimitry Andric 
3505f757f3fSDimitry Andric public:
3515f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {}
3525f757f3fSDimitry Andric 
3535f757f3fSDimitry Andric   __runtime_format_string(const __runtime_format_string&)            = delete;
3545f757f3fSDimitry Andric   __runtime_format_string& operator=(const __runtime_format_string&) = delete;
3555f757f3fSDimitry Andric };
3565f757f3fSDimitry Andric 
3575f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; }
3585f757f3fSDimitry Andric #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3595f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept {
3605f757f3fSDimitry Andric   return __fmt;
3615f757f3fSDimitry Andric }
3625f757f3fSDimitry Andric #    endif
3635f757f3fSDimitry Andric #  endif //_LIBCPP_STD_VER >= 26
3645f757f3fSDimitry Andric 
365bdd1243dSDimitry Andric template <class _CharT, class... _Args>
366bdd1243dSDimitry Andric struct _LIBCPP_TEMPLATE_VIS basic_format_string {
367bdd1243dSDimitry Andric   template <class _Tp>
368bdd1243dSDimitry Andric     requires convertible_to<const _Tp&, basic_string_view<_CharT>>
369bdd1243dSDimitry Andric   consteval basic_format_string(const _Tp& __str) : __str_{__str} {
370bdd1243dSDimitry Andric     __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
371bdd1243dSDimitry Andric                            _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
372bdd1243dSDimitry Andric   }
373bdd1243dSDimitry Andric 
374cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; }
3755f757f3fSDimitry Andric #  if _LIBCPP_STD_VER >= 26
3765f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI basic_format_string(__runtime_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {}
3775f757f3fSDimitry Andric #  endif
378bdd1243dSDimitry Andric 
379bdd1243dSDimitry Andric private:
380bdd1243dSDimitry Andric   basic_string_view<_CharT> __str_;
381bdd1243dSDimitry Andric 
382bdd1243dSDimitry Andric   using _Context = __format::__compile_time_basic_format_context<_CharT>;
383bdd1243dSDimitry Andric 
384bdd1243dSDimitry Andric   static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{
385bdd1243dSDimitry Andric       __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};
386bdd1243dSDimitry Andric 
387bdd1243dSDimitry Andric   static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {
388bdd1243dSDimitry Andric     using _Tp = remove_cvref_t<_Args>;
389bdd1243dSDimitry Andric     __format::__compile_time_handle<_CharT> __handle;
390bdd1243dSDimitry Andric     if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
391bdd1243dSDimitry Andric       __handle.template __enable<_Tp>();
392bdd1243dSDimitry Andric 
393bdd1243dSDimitry Andric     return __handle;
394bdd1243dSDimitry Andric   }()...};
395bdd1243dSDimitry Andric };
396bdd1243dSDimitry Andric 
397bdd1243dSDimitry Andric template <class... _Args>
398bdd1243dSDimitry Andric using format_string = basic_format_string<char, type_identity_t<_Args>...>;
399bdd1243dSDimitry Andric 
400bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
401bdd1243dSDimitry Andric template <class... _Args>
402bdd1243dSDimitry Andric using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>;
403bdd1243dSDimitry Andric #  endif
404bdd1243dSDimitry Andric 
405bdd1243dSDimitry Andric template <class _OutIt, class _CharT, class _FormatOutIt>
406cb14a3feSDimitry Andric   requires(output_iterator<_OutIt, const _CharT&>)
407cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it,
408cb14a3feSDimitry Andric                                           basic_string_view<_CharT> __fmt,
409bdd1243dSDimitry Andric                                           basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
410bdd1243dSDimitry Andric   if constexpr (same_as<_OutIt, _FormatOutIt>)
411cb14a3feSDimitry Andric     return std::__format::__vformat_to(
412cb14a3feSDimitry Andric         basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args));
413bdd1243dSDimitry Andric   else {
4145f757f3fSDimitry Andric     __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)};
4155f757f3fSDimitry Andric     std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
4165f757f3fSDimitry Andric                                 std::__format_context_create(__buffer.__make_output_iterator(), __args));
4175f757f3fSDimitry Andric     return std::move(__buffer).__out_it();
418bdd1243dSDimitry Andric   }
419bdd1243dSDimitry Andric }
420bdd1243dSDimitry Andric 
421bdd1243dSDimitry Andric // The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
422bdd1243dSDimitry Andric // https://reviews.llvm.org/D110499#inline-1180704
423bdd1243dSDimitry Andric // TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
424bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt>
425cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
4265f757f3fSDimitry Andric   return std::__vformat_to(std::move(__out_it), __fmt, __args);
427bdd1243dSDimitry Andric }
428bdd1243dSDimitry Andric 
429bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
430bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt>
43106c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
432bdd1243dSDimitry Andric vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
4335f757f3fSDimitry Andric   return std::__vformat_to(std::move(__out_it), __fmt, __args);
434bdd1243dSDimitry Andric }
435bdd1243dSDimitry Andric #  endif
436bdd1243dSDimitry Andric 
437bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args>
43806c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
439bdd1243dSDimitry Andric format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) {
440cb14a3feSDimitry Andric   return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_format_args(__args...));
441bdd1243dSDimitry Andric }
442bdd1243dSDimitry Andric 
443bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
444bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args>
44506c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
446bdd1243dSDimitry Andric format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {
447cb14a3feSDimitry Andric   return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_wformat_args(__args...));
448bdd1243dSDimitry Andric }
449bdd1243dSDimitry Andric #  endif
450bdd1243dSDimitry Andric 
45106c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
45206c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563.
45306c3fb27SDimitry Andric template <class = void>
454*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) {
455bdd1243dSDimitry Andric   string __res;
4565f757f3fSDimitry Andric   std::vformat_to(std::back_inserter(__res), __fmt, __args);
457bdd1243dSDimitry Andric   return __res;
458bdd1243dSDimitry Andric }
459bdd1243dSDimitry Andric 
460bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
46106c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
46206c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563.
46306c3fb27SDimitry Andric template <class = void>
464*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
465bdd1243dSDimitry Andric vformat(wstring_view __fmt, wformat_args __args) {
466bdd1243dSDimitry Andric   wstring __res;
4675f757f3fSDimitry Andric   std::vformat_to(std::back_inserter(__res), __fmt, __args);
468bdd1243dSDimitry Andric   return __res;
469bdd1243dSDimitry Andric }
470bdd1243dSDimitry Andric #  endif
471bdd1243dSDimitry Andric 
472bdd1243dSDimitry Andric template <class... _Args>
473*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string
47406c3fb27SDimitry Andric format(format_string<_Args...> __fmt, _Args&&... __args) {
4755f757f3fSDimitry Andric   return std::vformat(__fmt.get(), std::make_format_args(__args...));
476bdd1243dSDimitry Andric }
477bdd1243dSDimitry Andric 
478bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
479bdd1243dSDimitry Andric template <class... _Args>
480*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring
481bdd1243dSDimitry Andric format(wformat_string<_Args...> __fmt, _Args&&... __args) {
4825f757f3fSDimitry Andric   return std::vformat(__fmt.get(), std::make_wformat_args(__args...));
483bdd1243dSDimitry Andric }
484bdd1243dSDimitry Andric #  endif
485bdd1243dSDimitry Andric 
486bdd1243dSDimitry Andric template <class _Context, class _OutIt, class _CharT>
487cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
488cb14a3feSDimitry Andric __vformat_to_n(_OutIt __out_it,
489cb14a3feSDimitry Andric                iter_difference_t<_OutIt> __n,
490bdd1243dSDimitry Andric                basic_string_view<_CharT> __fmt,
491bdd1243dSDimitry Andric                basic_format_args<_Context> __args) {
4925f757f3fSDimitry Andric   __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n};
4935f757f3fSDimitry Andric   std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
4945f757f3fSDimitry Andric                               std::__format_context_create(__buffer.__make_output_iterator(), __args));
4955f757f3fSDimitry Andric   return std::move(__buffer).__result();
496bdd1243dSDimitry Andric }
497bdd1243dSDimitry Andric 
498bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args>
49906c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
500bdd1243dSDimitry Andric format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) {
5015f757f3fSDimitry Andric   return std::__vformat_to_n<format_context>(std::move(__out_it), __n, __fmt.get(), std::make_format_args(__args...));
502bdd1243dSDimitry Andric }
503bdd1243dSDimitry Andric 
504bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
505bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args>
50606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
507cb14a3feSDimitry Andric format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) {
5085f757f3fSDimitry Andric   return std::__vformat_to_n<wformat_context>(std::move(__out_it), __n, __fmt.get(), std::make_wformat_args(__args...));
509bdd1243dSDimitry Andric }
510bdd1243dSDimitry Andric #  endif
511bdd1243dSDimitry Andric 
512bdd1243dSDimitry Andric template <class _CharT>
513bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
514bdd1243dSDimitry Andric   __format::__formatted_size_buffer<_CharT> __buffer;
5155f757f3fSDimitry Andric   std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
5165f757f3fSDimitry Andric                               std::__format_context_create(__buffer.__make_output_iterator(), __args));
5175f757f3fSDimitry Andric   return std::move(__buffer).__result();
518bdd1243dSDimitry Andric }
519bdd1243dSDimitry Andric 
520bdd1243dSDimitry Andric template <class... _Args>
521*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
522bdd1243dSDimitry Andric formatted_size(format_string<_Args...> __fmt, _Args&&... __args) {
5235f757f3fSDimitry Andric   return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)});
524bdd1243dSDimitry Andric }
525bdd1243dSDimitry Andric 
526bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
527bdd1243dSDimitry Andric template <class... _Args>
528*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
529bdd1243dSDimitry Andric formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) {
5305f757f3fSDimitry Andric   return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)});
531bdd1243dSDimitry Andric }
532bdd1243dSDimitry Andric #  endif
533bdd1243dSDimitry Andric 
534bdd1243dSDimitry Andric #  ifndef _LIBCPP_HAS_NO_LOCALIZATION
535bdd1243dSDimitry Andric 
536bdd1243dSDimitry Andric template <class _OutIt, class _CharT, class _FormatOutIt>
537cb14a3feSDimitry Andric   requires(output_iterator<_OutIt, const _CharT&>)
538cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(
539cb14a3feSDimitry Andric     _OutIt __out_it,
540cb14a3feSDimitry Andric     locale __loc,
541cb14a3feSDimitry Andric     basic_string_view<_CharT> __fmt,
542bdd1243dSDimitry Andric     basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
543bdd1243dSDimitry Andric   if constexpr (same_as<_OutIt, _FormatOutIt>)
544cb14a3feSDimitry Andric     return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
5455f757f3fSDimitry Andric                                        std::__format_context_create(std::move(__out_it), __args, std::move(__loc)));
546bdd1243dSDimitry Andric   else {
5475f757f3fSDimitry Andric     __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)};
5485f757f3fSDimitry Andric     std::__format::__vformat_to(
549bdd1243dSDimitry Andric         basic_format_parse_context{__fmt, __args.__size()},
5505f757f3fSDimitry Andric         std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));
5515f757f3fSDimitry Andric     return std::move(__buffer).__out_it();
552bdd1243dSDimitry Andric   }
553bdd1243dSDimitry Andric }
554bdd1243dSDimitry Andric 
555bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt>
556cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
557cb14a3feSDimitry Andric vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
558cb14a3feSDimitry Andric   return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args);
559bdd1243dSDimitry Andric }
560bdd1243dSDimitry Andric 
561bdd1243dSDimitry Andric #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
562bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt>
563cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
564cb14a3feSDimitry Andric vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
565cb14a3feSDimitry Andric   return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args);
566bdd1243dSDimitry Andric }
567bdd1243dSDimitry Andric #    endif
568bdd1243dSDimitry Andric 
569bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args>
57006c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
571bdd1243dSDimitry Andric format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
572cb14a3feSDimitry Andric   return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_format_args(__args...));
573bdd1243dSDimitry Andric }
574bdd1243dSDimitry Andric 
575bdd1243dSDimitry Andric #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
576bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args>
57706c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
578bdd1243dSDimitry Andric format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
579cb14a3feSDimitry Andric   return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));
580bdd1243dSDimitry Andric }
581bdd1243dSDimitry Andric #    endif
582bdd1243dSDimitry Andric 
58306c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
58406c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563.
58506c3fb27SDimitry Andric template <class = void>
586*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string
587bdd1243dSDimitry Andric vformat(locale __loc, string_view __fmt, format_args __args) {
588bdd1243dSDimitry Andric   string __res;
589cb14a3feSDimitry Andric   std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args);
590bdd1243dSDimitry Andric   return __res;
591bdd1243dSDimitry Andric }
592bdd1243dSDimitry Andric 
593bdd1243dSDimitry Andric #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
59406c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
59506c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563.
59606c3fb27SDimitry Andric template <class = void>
597*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
598bdd1243dSDimitry Andric vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
599bdd1243dSDimitry Andric   wstring __res;
600cb14a3feSDimitry Andric   std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args);
601bdd1243dSDimitry Andric   return __res;
602bdd1243dSDimitry Andric }
603bdd1243dSDimitry Andric #    endif
604bdd1243dSDimitry Andric 
605bdd1243dSDimitry Andric template <class... _Args>
606*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string
60706c3fb27SDimitry Andric format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
608cb14a3feSDimitry Andric   return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...));
609bdd1243dSDimitry Andric }
610bdd1243dSDimitry Andric 
611bdd1243dSDimitry Andric #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
612bdd1243dSDimitry Andric template <class... _Args>
613*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring
614bdd1243dSDimitry Andric format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
615cb14a3feSDimitry Andric   return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));
616bdd1243dSDimitry Andric }
617bdd1243dSDimitry Andric #    endif
618bdd1243dSDimitry Andric 
619bdd1243dSDimitry Andric template <class _Context, class _OutIt, class _CharT>
620cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(
621cb14a3feSDimitry Andric     _OutIt __out_it,
622cb14a3feSDimitry Andric     iter_difference_t<_OutIt> __n,
623cb14a3feSDimitry Andric     locale __loc,
624cb14a3feSDimitry Andric     basic_string_view<_CharT> __fmt,
625bdd1243dSDimitry Andric     basic_format_args<_Context> __args) {
6265f757f3fSDimitry Andric   __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n};
6275f757f3fSDimitry Andric   std::__format::__vformat_to(
628bdd1243dSDimitry Andric       basic_format_parse_context{__fmt, __args.__size()},
6295f757f3fSDimitry Andric       std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));
6305f757f3fSDimitry Andric   return std::move(__buffer).__result();
631bdd1243dSDimitry Andric }
632bdd1243dSDimitry Andric 
633bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args>
634cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(
635cb14a3feSDimitry Andric     _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
636cb14a3feSDimitry Andric   return std::__vformat_to_n<format_context>(
637cb14a3feSDimitry Andric       std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_format_args(__args...));
638bdd1243dSDimitry Andric }
639bdd1243dSDimitry Andric 
640bdd1243dSDimitry Andric #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
641bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args>
642cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(
643cb14a3feSDimitry Andric     _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
644cb14a3feSDimitry Andric   return std::__vformat_to_n<wformat_context>(
645cb14a3feSDimitry Andric       std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));
646bdd1243dSDimitry Andric }
647bdd1243dSDimitry Andric #    endif
648bdd1243dSDimitry Andric 
649bdd1243dSDimitry Andric template <class _CharT>
650bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
651bdd1243dSDimitry Andric   __format::__formatted_size_buffer<_CharT> __buffer;
6525f757f3fSDimitry Andric   std::__format::__vformat_to(
653bdd1243dSDimitry Andric       basic_format_parse_context{__fmt, __args.__size()},
6545f757f3fSDimitry Andric       std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));
6555f757f3fSDimitry Andric   return std::move(__buffer).__result();
656bdd1243dSDimitry Andric }
657bdd1243dSDimitry Andric 
658bdd1243dSDimitry Andric template <class... _Args>
659*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
660bdd1243dSDimitry Andric formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
6615f757f3fSDimitry Andric   return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)});
662bdd1243dSDimitry Andric }
663bdd1243dSDimitry Andric 
664bdd1243dSDimitry Andric #    ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
665bdd1243dSDimitry Andric template <class... _Args>
666*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
667bdd1243dSDimitry Andric formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
6685f757f3fSDimitry Andric   return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)});
669bdd1243dSDimitry Andric }
670bdd1243dSDimitry Andric #    endif
671bdd1243dSDimitry Andric 
672bdd1243dSDimitry Andric #  endif // _LIBCPP_HAS_NO_LOCALIZATION
673bdd1243dSDimitry Andric 
67406c3fb27SDimitry Andric #endif //_LIBCPP_STD_VER >= 20
675bdd1243dSDimitry Andric 
676bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD
677bdd1243dSDimitry Andric 
678b3edf446SDimitry Andric _LIBCPP_POP_MACROS
679b3edf446SDimitry Andric 
680bdd1243dSDimitry Andric #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS
681