2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_FORMAT
11 #define _LIBCPP_FORMAT
16 // [format.context], class template basic_format_context
17 template<class Out, class charT> class basic_format_context;
18 using format_context = basic_format_context<unspecified, char>;
19 using wformat_context = basic_format_context<unspecified, wchar_t>;
21 // [format.args], class template basic_format_args
22 template<class Context> class basic_format_args;
23 using format_args = basic_format_args<format_context>;
24 using wformat_args = basic_format_args<wformat_context>;
26 // [format.fmt.string], class template basic-format-string
27 template<class charT, class... Args>
28 struct basic-format-string; // exposition only
30 template<class... Args>
31 using format-string = // exposition only
32 basic-format-string<char, type_identity_t<Args>...>;
33 template<class... Args>
34 using wformat-string = // exposition only
35 basic-format-string<wchar_t, type_identity_t<Args>...>;
37 // [format.functions], formatting functions
38 template<class... Args>
39 string format(format-string<Args...> fmt, Args&&... args);
40 template<class... Args>
41 wstring format(wformat-string<Args...> fmt, Args&&... args);
42 template<class... Args>
43 string format(const locale& loc, format-string<Args...> fmt, Args&&... args);
44 template<class... Args>
45 wstring format(const locale& loc, wformat-string<Args...> fmt, Args&&... args);
47 string vformat(string_view fmt, format_args args);
48 wstring vformat(wstring_view fmt, wformat_args args);
49 string vformat(const locale& loc, string_view fmt, format_args args);
50 wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
52 template<class Out, class... Args>
53 Out format_to(Out out, format-string<Args...> fmt, Args&&... args);
54 template<class Out, class... Args>
55 Out format_to(Out out, wformat-string<Args...> fmt, Args&&... args);
56 template<class Out, class... Args>
57 Out format_to(Out out, const locale& loc, format-string<Args...> fmt, Args&&... args);
58 template<class Out, class... Args>
59 Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, Args&&... args);
62 Out vformat_to(Out out, string_view fmt, format_args args);
64 Out vformat_to(Out out, wstring_view fmt, wformat_args args);
66 Out vformat_to(Out out, const locale& loc, string_view fmt,
67 format_args char> args);
69 Out vformat_to(Out out, const locale& loc, wstring_view fmt,
72 template<class Out> struct format_to_n_result {
74 iter_difference_t<Out> size;
76 template<class Out, class... Args>
77 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
78 format-string<Args...> fmt, Args&&... args);
79 template<class Out, class... Args>
80 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
81 wformat-string<Args...> fmt, Args&&... args);
82 template<class Out, class... Args>
83 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
84 const locale& loc, format-string<Args...> fmt,
86 template<class Out, class... Args>
87 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
88 const locale& loc, wformat-string<Args...> fmt,
91 template<class... Args>
92 size_t formatted_size(format-string<Args...> fmt, Args&&... args);
93 template<class... Args>
94 size_t formatted_size(wformat-string<Args...> fmt, Args&&... args);
95 template<class... Args>
96 size_t formatted_size(const locale& loc, format-string<Args...> fmt, Args&&... args);
97 template<class... Args>
98 size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, Args&&... args);
100 // [format.formatter], formatter
101 template<class T, class charT = char> struct formatter;
103 // [format.parse.ctx], class template basic_format_parse_context
104 template<class charT> class basic_format_parse_context;
105 using format_parse_context = basic_format_parse_context<char>;
106 using wformat_parse_context = basic_format_parse_context<wchar_t>;
108 // [format.arguments], arguments
109 // [format.arg], class template basic_format_arg
110 template<class Context> class basic_format_arg;
112 template<class Visitor, class Context>
113 see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
115 // [format.arg.store], class template format-arg-store
116 template<class Context, class... Args> struct format-arg-store; // exposition only
118 template<class Context = format_context, class... Args>
119 format-arg-store<Context, Args...>
120 make_format_args(Args&&... args);
121 template<class... Args>
122 format-arg-store<wformat_context, Args...>
123 make_wformat_args(Args&&... args);
125 // [format.error], class format_error
131 #include <__assert> // all public C++ headers provide the assertion handler
132 // Make sure all feature-test macros are available.
134 // Enable the contents of the header only when libc++ was built with experimental features enabled.
135 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
137 #include <__algorithm/clamp.h>
140 #include <__format/buffer.h>
141 #include <__format/concepts.h>
142 #include <__format/enable_insertable.h>
143 #include <__format/format_arg.h>
144 #include <__format/format_arg_store.h>
145 #include <__format/format_args.h>
146 #include <__format/format_context.h>
147 #include <__format/format_error.h>
148 #include <__format/format_fwd.h>
149 #include <__format/format_parse_context.h>
150 #include <__format/format_string.h>
151 #include <__format/format_to_n_result.h>
152 #include <__format/formatter.h>
153 #include <__format/formatter_bool.h>
154 #include <__format/formatter_char.h>
155 #include <__format/formatter_floating_point.h>
156 #include <__format/formatter_integer.h>
157 #include <__format/formatter_pointer.h>
158 #include <__format/formatter_string.h>
159 #include <__format/parser_std_format_spec.h>
160 #include <__format/unicode.h>
161 #include <__iterator/back_insert_iterator.h>
162 #include <__iterator/incrementable_traits.h>
163 #include <__variant/monostate.h>
167 #include <string_view>
168 #include <type_traits>
170 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
174 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
175 # pragma GCC system_header
178 _LIBCPP_BEGIN_NAMESPACE_STD
180 #if _LIBCPP_STD_VER > 17
182 // TODO FMT Move the implementation in this file to its own granular headers.
184 // TODO FMT Evaluate which templates should be external templates. This
185 // improves the efficiency of the header. However since the header is still
186 // under heavy development and not all classes are stable it makes no sense
187 // to do this optimization now.
189 using format_args = basic_format_args<format_context>;
190 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
191 using wformat_args = basic_format_args<wformat_context>;
194 template <class _Context = format_context, class... _Args>
195 _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) {
196 return _VSTD::__format_arg_store<_Context, _Args...>(__args...);
199 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
200 template <class... _Args>
201 _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) {
202 return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...);
208 /// Helper class parse and handle argument.
210 /// When parsing a handle which is not enabled the code is ill-formed.
211 /// This helper uses the parser of the appropriate formatter for the stored type.
212 template <class _CharT>
213 class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
215 _LIBCPP_HIDE_FROM_ABI
216 constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); }
219 _LIBCPP_HIDE_FROM_ABI constexpr void __enable() {
220 __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) {
221 formatter<_Tp, _CharT> __f;
222 __parse_ctx.advance_to(__f.parse(__parse_ctx));
226 // Before calling __parse the proper handler needs to be set with __enable.
227 // The default handler isn't a core constant expression.
228 _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()
229 : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {}
232 void (*__parse_)(basic_format_parse_context<_CharT>&);
235 // Dummy format_context only providing the parts used during constant
236 // validation of the basic-format-string.
237 template <class _CharT>
238 struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context {
240 using char_type = _CharT;
242 _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(
243 const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)
244 : __args_(__args), __handles_(__handles), __size_(__size) {}
246 // During the compile-time validation nothing needs to be written.
247 // Therefore all operations of this iterator are a NOP.
249 _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }
250 _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }
251 _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }
254 _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
256 __throw_format_error("Argument index out of bounds");
257 return __args_[__id];
260 _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {
262 __throw_format_error("Argument index out of bounds");
263 return __handles_[__id];
266 _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }
267 _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}
270 const __arg_t* __args_;
271 const __compile_time_handle<_CharT>* __handles_;
275 _LIBCPP_HIDE_FROM_ABI
276 constexpr void __compile_time_validate_integral(__arg_t __type) {
279 case __arg_t::__long_long:
280 case __arg_t::__i128:
281 case __arg_t::__unsigned:
282 case __arg_t::__unsigned_long_long:
283 case __arg_t::__u128:
287 __throw_format_error("Argument isn't an integral type");
291 // _HasPrecision does the formatter have a precision?
292 template <class _CharT, class _Tp, bool _HasPrecision = false>
293 _LIBCPP_HIDE_FROM_ABI constexpr void
294 __compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx,
295 __compile_time_basic_format_context<_CharT>& __ctx) {
296 formatter<_Tp, _CharT> __formatter;
297 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
298 // [format.string.std]/7
299 // ... If the corresponding formatting argument is not of integral type, or
300 // its value is negative for precision or non-positive for width, an
301 // exception of type format_error is thrown.
303 // Validate whether the arguments are integrals.
304 if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) {
305 // TODO FMT Remove this when parser v1 has been phased out.
306 if (__formatter.__width_needs_substitution())
307 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__width));
309 if constexpr (_HasPrecision)
310 if (__formatter.__precision_needs_substitution())
311 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision));
313 if (__formatter.__parser_.__width_as_arg_)
314 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_));
316 if constexpr (_HasPrecision)
317 if (__formatter.__parser_.__precision_as_arg_)
318 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_));
322 template <class _CharT>
323 _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx,
324 __compile_time_basic_format_context<_CharT>& __ctx,
327 case __arg_t::__none:
328 __throw_format_error("Invalid argument");
329 case __arg_t::__boolean:
330 return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);
331 case __arg_t::__char_type:
332 return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);
334 return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);
335 case __arg_t::__long_long:
336 return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);
337 case __arg_t::__i128:
338 # ifndef _LIBCPP_HAS_NO_INT128
339 return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);
341 __throw_format_error("Invalid argument");
344 case __arg_t::__unsigned:
345 return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);
346 case __arg_t::__unsigned_long_long:
347 return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);
348 case __arg_t::__u128:
349 # ifndef _LIBCPP_HAS_NO_INT128
350 return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);
352 __throw_format_error("Invalid argument");
355 case __arg_t::__float:
356 return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);
357 case __arg_t::__double:
358 return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);
359 case __arg_t::__long_double:
360 return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);
361 case __arg_t::__const_char_type_ptr:
362 return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);
363 case __arg_t::__string_view:
364 return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);
366 return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);
367 case __arg_t::__handle:
368 __throw_format_error("Handle should use __compile_time_validate_handle_argument");
370 __throw_format_error("Invalid argument");
373 template <class _CharT, class _ParseCtx, class _Ctx>
374 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
375 __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
376 _ParseCtx& __parse_ctx, _Ctx& __ctx) {
377 __format::__parse_number_result __r =
378 __format::__parse_arg_id(__begin, __end, __parse_ctx);
380 bool __parse = *__r.__ptr == _CharT(':');
381 switch (*__r.__ptr) {
383 // The arg-id has a format-specifier, advance the input to the format-spec.
384 __parse_ctx.advance_to(__r.__ptr + 1);
387 // The arg-id has no format-specifier.
388 __parse_ctx.advance_to(__r.__ptr);
391 __throw_format_error(
392 "The replacement field arg-id should terminate at a ':' or '}'");
395 if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
396 __arg_t __type = __ctx.arg(__r.__value);
397 if (__type == __arg_t::__handle)
398 __ctx.__handle(__r.__value).__parse(__parse_ctx);
400 __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
402 _VSTD::visit_format_arg(
404 if constexpr (same_as<decltype(__arg), monostate>)
405 __throw_format_error("Argument index out of bounds");
406 else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
407 __arg.format(__parse_ctx, __ctx);
409 formatter<decltype(__arg), _CharT> __formatter;
411 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
412 __ctx.advance_to(__formatter.format(__arg, __ctx));
415 __ctx.arg(__r.__value));
417 __begin = __parse_ctx.begin();
418 if (__begin == __end || *__begin != _CharT('}'))
419 __throw_format_error("The replacement field misses a terminating '}'");
424 template <class _ParseCtx, class _Ctx>
425 _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator
426 __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
427 using _CharT = typename _ParseCtx::char_type;
428 static_assert(same_as<typename _Ctx::char_type, _CharT>);
430 const _CharT* __begin = __parse_ctx.begin();
431 const _CharT* __end = __parse_ctx.end();
432 typename _Ctx::iterator __out_it = __ctx.out();
433 while (__begin != __end) {
437 if (__begin == __end)
438 __throw_format_error("The format string terminates at a '{'");
440 if (*__begin != _CharT('{')) [[likely]] {
441 __ctx.advance_to(_VSTD::move(__out_it));
443 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
444 __out_it = __ctx.out();
446 // The output is written and __begin points to the next character. So
447 // start the next iteration.
450 // The string is an escape character.
455 if (__begin == __end || *__begin != _CharT('}'))
456 __throw_format_error(
457 "The format string contains an invalid escape sequence");
462 // Copy the character to the output verbatim.
463 *__out_it++ = *__begin++;
468 } // namespace __format
470 template <class _CharT, class... _Args>
471 struct _LIBCPP_TEMPLATE_VIS __basic_format_string {
472 basic_string_view<_CharT> __str_;
475 requires convertible_to<const _Tp&, basic_string_view<_CharT>>
476 consteval __basic_format_string(const _Tp& __str) : __str_{__str} {
477 __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
478 _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
482 using _Context = __format::__compile_time_basic_format_context<_CharT>;
484 static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{
485 __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};
487 // TODO FMT remove this work-around when the AIX ICE has been resolved.
488 # if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400
490 static constexpr __format::__compile_time_handle<_CharT> __get_handle() {
491 __format::__compile_time_handle<_CharT> __handle;
492 if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
493 __handle.template __enable<_Tp>();
498 static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{
499 __get_handle<_Args>()...};
501 static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {
502 using _Tp = remove_cvref_t<_Args>;
503 __format::__compile_time_handle<_CharT> __handle;
504 if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
505 __handle.template __enable<_Tp>();
512 template <class... _Args>
513 using __format_string_t = __basic_format_string<char, type_identity_t<_Args>...>;
515 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
516 template <class... _Args>
517 using __wformat_string_t = __basic_format_string<wchar_t, type_identity_t<_Args>...>;
520 template <class _OutIt, class _CharT, class _FormatOutIt>
521 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
523 _OutIt __out_it, basic_string_view<_CharT> __fmt,
524 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
525 if constexpr (same_as<_OutIt, _FormatOutIt>)
526 return _VSTD::__format::__vformat_to(
527 basic_format_parse_context{__fmt, __args.__size()},
528 _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
530 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
531 _VSTD::__format::__vformat_to(
532 basic_format_parse_context{__fmt, __args.__size()},
533 _VSTD::__format_context_create(__buffer.make_output_iterator(),
535 return _VSTD::move(__buffer).out();
539 // The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
540 // https://reviews.llvm.org/D110499#inline-1180704
541 // TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
542 template <output_iterator<const char&> _OutIt>
543 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
544 vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
545 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
548 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
549 template <output_iterator<const wchar_t&> _OutIt>
550 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
551 vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
552 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
556 template <output_iterator<const char&> _OutIt, class... _Args>
557 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
558 format_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, _Args&&... __args) {
559 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_,
560 _VSTD::make_format_args(__args...));
563 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
564 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
565 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
566 format_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
567 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_,
568 _VSTD::make_wformat_args(__args...));
572 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
573 vformat(string_view __fmt, format_args __args) {
575 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
579 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
580 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
581 vformat(wstring_view __fmt, wformat_args __args) {
583 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
588 template <class... _Args>
589 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt,
591 return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...));
594 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
595 template <class... _Args>
596 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
597 format(__wformat_string_t<_Args...> __fmt, _Args&&... __args) {
598 return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...));
602 template <class _Context, class _OutIt, class _CharT>
603 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
604 basic_string_view<_CharT> __fmt,
605 basic_format_args<_Context> __args) {
606 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
607 _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
608 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
609 return _VSTD::move(__buffer).result();
612 template <output_iterator<const char&> _OutIt, class... _Args>
613 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
614 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, _Args&&... __args) {
615 return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...));
618 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
619 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
620 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
621 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt,
623 return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...));
627 template <class _CharT>
628 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
629 __format::__formatted_size_buffer<_CharT> __buffer;
630 _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
631 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
632 return _VSTD::move(__buffer).result();
635 template <class... _Args>
636 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
637 formatted_size(__format_string_t<_Args...> __fmt, _Args&&... __args) {
638 return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)});
641 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
642 template <class... _Args>
643 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
644 formatted_size(__wformat_string_t<_Args...> __fmt, _Args&&... __args) {
645 return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)});
649 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
651 template <class _OutIt, class _CharT, class _FormatOutIt>
652 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
654 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
655 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
656 if constexpr (same_as<_OutIt, _FormatOutIt>)
657 return _VSTD::__format::__vformat_to(
658 basic_format_parse_context{__fmt, __args.__size()},
659 _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
660 _VSTD::move(__loc)));
662 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
663 _VSTD::__format::__vformat_to(
664 basic_format_parse_context{__fmt, __args.__size()},
665 _VSTD::__format_context_create(__buffer.make_output_iterator(),
666 __args, _VSTD::move(__loc)));
667 return _VSTD::move(__buffer).out();
671 template <output_iterator<const char&> _OutIt>
672 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
673 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
674 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
678 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
679 template <output_iterator<const wchar_t&> _OutIt>
680 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
681 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
682 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
687 template <output_iterator<const char&> _OutIt, class... _Args>
688 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
689 format_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) {
690 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_,
691 _VSTD::make_format_args(__args...));
694 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
695 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
696 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
697 format_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
698 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_,
699 _VSTD::make_wformat_args(__args...));
703 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
704 vformat(locale __loc, string_view __fmt, format_args __args) {
706 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
711 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
712 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
713 vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
715 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
721 template <class... _Args>
722 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc,
723 __format_string_t<_Args...> __fmt,
725 return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_,
726 _VSTD::make_format_args(__args...));
729 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
730 template <class... _Args>
731 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
732 format(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
733 return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_,
734 _VSTD::make_wformat_args(__args...));
738 template <class _Context, class _OutIt, class _CharT>
739 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
740 locale __loc, basic_string_view<_CharT> __fmt,
741 basic_format_args<_Context> __args) {
742 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
743 _VSTD::__format::__vformat_to(
744 basic_format_parse_context{__fmt, __args.__size()},
745 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
746 return _VSTD::move(__buffer).result();
749 template <output_iterator<const char&> _OutIt, class... _Args>
750 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
751 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt,
753 return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_,
754 _VSTD::make_format_args(__args...));
757 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
758 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
759 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
760 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt,
762 return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_,
763 _VSTD::make_wformat_args(__args...));
767 template <class _CharT>
768 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
769 __format::__formatted_size_buffer<_CharT> __buffer;
770 _VSTD::__format::__vformat_to(
771 basic_format_parse_context{__fmt, __args.__size()},
772 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
773 return _VSTD::move(__buffer).result();
776 template <class... _Args>
777 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
778 formatted_size(locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) {
779 return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)});
782 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
783 template <class... _Args>
784 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
785 formatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
786 return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)});
790 #endif // _LIBCPP_HAS_NO_LOCALIZATION
792 #endif //_LIBCPP_STD_VER > 17
794 _LIBCPP_END_NAMESPACE_STD
796 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
798 #endif // _LIBCPP_FORMAT