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