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 11#define _LIBCPP_FORMAT 12 13/* 14 15namespace std { 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>; 20 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>; 25 26 // [format.fmt.string], class template basic_format_string 27 template<class charT, class... Args> 28 struct basic_format_string { // since C++23, exposition only before C++23 29 private: 30 basic_string_view<charT> str; // exposition only 31 32 public: 33 template<class T> consteval basic_format_string(const T& s); 34 35 constexpr basic_string_view<charT> get() const noexcept { return str; } 36 }; 37 template<class... Args> 38 using format_string = // since C++23, exposition only before C++23 39 basic_format_string<char, type_identity_t<Args>...>; 40 template<class... Args> 41 using wformat_string = // since C++23, exposition only before C++23 42 basic_format_string<wchar_t, type_identity_t<Args>...>; 43 44 // [format.functions], formatting functions 45 template<class... Args> 46 string format(format-string<Args...> fmt, Args&&... args); 47 template<class... Args> 48 wstring format(wformat-string<Args...> fmt, Args&&... args); 49 template<class... Args> 50 string format(const locale& loc, format-string<Args...> fmt, Args&&... args); 51 template<class... Args> 52 wstring format(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 53 54 string vformat(string_view fmt, format_args args); 55 wstring vformat(wstring_view fmt, wformat_args args); 56 string vformat(const locale& loc, string_view fmt, format_args args); 57 wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); 58 59 template<class Out, class... Args> 60 Out format_to(Out out, format-string<Args...> fmt, Args&&... args); 61 template<class Out, class... Args> 62 Out format_to(Out out, wformat-string<Args...> fmt, Args&&... args); 63 template<class Out, class... Args> 64 Out format_to(Out out, const locale& loc, format-string<Args...> fmt, Args&&... args); 65 template<class Out, class... Args> 66 Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, Args&&... args); 67 68 template<class Out> 69 Out vformat_to(Out out, string_view fmt, format_args args); 70 template<class Out> 71 Out vformat_to(Out out, wstring_view fmt, wformat_args args); 72 template<class Out> 73 Out vformat_to(Out out, const locale& loc, string_view fmt, 74 format_args char> args); 75 template<class Out> 76 Out vformat_to(Out out, const locale& loc, wstring_view fmt, 77 wformat_args args); 78 79 template<class Out> struct format_to_n_result { 80 Out out; 81 iter_difference_t<Out> size; 82 }; 83 template<class Out, class... Args> 84 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 85 format-string<Args...> fmt, Args&&... args); 86 template<class Out, class... Args> 87 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 88 wformat-string<Args...> fmt, Args&&... args); 89 template<class Out, class... Args> 90 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 91 const locale& loc, format-string<Args...> fmt, 92 Args&&... args); 93 template<class Out, class... Args> 94 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 95 const locale& loc, wformat-string<Args...> fmt, 96 Args&&... args); 97 98 template<class... Args> 99 size_t formatted_size(format-string<Args...> fmt, Args&&... args); 100 template<class... Args> 101 size_t formatted_size(wformat-string<Args...> fmt, Args&&... args); 102 template<class... Args> 103 size_t formatted_size(const locale& loc, format-string<Args...> fmt, Args&&... args); 104 template<class... Args> 105 size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 106 107 // [format.formatter], formatter 108 template<class T, class charT = char> struct formatter; 109 110 // [format.parse.ctx], class template basic_format_parse_context 111 template<class charT> class basic_format_parse_context; 112 using format_parse_context = basic_format_parse_context<char>; 113 using wformat_parse_context = basic_format_parse_context<wchar_t>; 114 115 // [format.arguments], arguments 116 // [format.arg], class template basic_format_arg 117 template<class Context> class basic_format_arg; 118 119 template<class Visitor, class Context> 120 see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); 121 122 // [format.arg.store], class template format-arg-store 123 template<class Context, class... Args> struct format-arg-store; // exposition only 124 125 template<class Context = format_context, class... Args> 126 format-arg-store<Context, Args...> 127 make_format_args(Args&&... args); 128 template<class... Args> 129 format-arg-store<wformat_context, Args...> 130 make_wformat_args(Args&&... args); 131 132 // [format.error], class format_error 133 class format_error; 134} 135 136*/ 137 138#include <__assert> // all public C++ headers provide the assertion handler 139// Make sure all feature-test macros are available. 140#include <version> 141// Enable the contents of the header only when libc++ was built with experimental features enabled. 142#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 143 144#include <__algorithm/clamp.h> 145#include <__config> 146#include <__debug> 147#include <__format/buffer.h> 148#include <__format/concepts.h> 149#include <__format/enable_insertable.h> 150#include <__format/format_arg.h> 151#include <__format/format_arg_store.h> 152#include <__format/format_args.h> 153#include <__format/format_context.h> 154#include <__format/format_error.h> 155#include <__format/format_fwd.h> 156#include <__format/format_parse_context.h> 157#include <__format/format_string.h> 158#include <__format/format_to_n_result.h> 159#include <__format/formatter.h> 160#include <__format/formatter_bool.h> 161#include <__format/formatter_char.h> 162#include <__format/formatter_floating_point.h> 163#include <__format/formatter_integer.h> 164#include <__format/formatter_pointer.h> 165#include <__format/formatter_string.h> 166#include <__format/parser_std_format_spec.h> 167#include <__format/unicode.h> 168#include <__iterator/back_insert_iterator.h> 169#include <__iterator/incrementable_traits.h> 170#include <__variant/monostate.h> 171#include <array> 172#include <concepts> 173#include <string> 174#include <string_view> 175#include <type_traits> 176 177#ifndef _LIBCPP_HAS_NO_LOCALIZATION 178#include <locale> 179#endif 180 181#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 182# pragma GCC system_header 183#endif 184 185_LIBCPP_BEGIN_NAMESPACE_STD 186 187#if _LIBCPP_STD_VER > 17 188 189// TODO FMT Move the implementation in this file to its own granular headers. 190 191// TODO FMT Evaluate which templates should be external templates. This 192// improves the efficiency of the header. However since the header is still 193// under heavy development and not all classes are stable it makes no sense 194// to do this optimization now. 195 196using format_args = basic_format_args<format_context>; 197#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 198using wformat_args = basic_format_args<wformat_context>; 199#endif 200 201template <class _Context = format_context, class... _Args> 202_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { 203 return _VSTD::__format_arg_store<_Context, _Args...>(__args...); 204} 205 206#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 207template <class... _Args> 208_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) { 209 return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...); 210} 211#endif 212 213namespace __format { 214 215/// Helper class parse and handle argument. 216/// 217/// When parsing a handle which is not enabled the code is ill-formed. 218/// This helper uses the parser of the appropriate formatter for the stored type. 219template <class _CharT> 220class _LIBCPP_TEMPLATE_VIS __compile_time_handle { 221public: 222 _LIBCPP_HIDE_FROM_ABI 223 constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } 224 225 template <class _Tp> 226 _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 227 __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { 228 formatter<_Tp, _CharT> __f; 229 __parse_ctx.advance_to(__f.parse(__parse_ctx)); 230 }; 231 } 232 233 // Before calling __parse the proper handler needs to be set with __enable. 234 // The default handler isn't a core constant expression. 235 _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 236 : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {} 237 238private: 239 void (*__parse_)(basic_format_parse_context<_CharT>&); 240}; 241 242// Dummy format_context only providing the parts used during constant 243// validation of the basic_format_string. 244template <class _CharT> 245struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 246public: 247 using char_type = _CharT; 248 249 _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 250 const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 251 : __args_(__args), __handles_(__handles), __size_(__size) {} 252 253 // During the compile-time validation nothing needs to be written. 254 // Therefore all operations of this iterator are a NOP. 255 struct iterator { 256 _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 257 _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 258 _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 259 }; 260 261 _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 262 if (__id >= __size_) 263 __throw_format_error("Argument index out of bounds"); 264 return __args_[__id]; 265 } 266 267 _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 268 if (__id >= __size_) 269 __throw_format_error("Argument index out of bounds"); 270 return __handles_[__id]; 271 } 272 273 _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 274 _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 275 276private: 277 const __arg_t* __args_; 278 const __compile_time_handle<_CharT>* __handles_; 279 size_t __size_; 280}; 281 282_LIBCPP_HIDE_FROM_ABI 283constexpr void __compile_time_validate_integral(__arg_t __type) { 284 switch (__type) { 285 case __arg_t::__int: 286 case __arg_t::__long_long: 287 case __arg_t::__i128: 288 case __arg_t::__unsigned: 289 case __arg_t::__unsigned_long_long: 290 case __arg_t::__u128: 291 return; 292 293 default: 294 __throw_format_error("Argument isn't an integral type"); 295 } 296} 297 298// _HasPrecision does the formatter have a precision? 299template <class _CharT, class _Tp, bool _HasPrecision = false> 300_LIBCPP_HIDE_FROM_ABI constexpr void 301__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, 302 __compile_time_basic_format_context<_CharT>& __ctx) { 303 formatter<_Tp, _CharT> __formatter; 304 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 305 // [format.string.std]/7 306 // ... If the corresponding formatting argument is not of integral type, or 307 // its value is negative for precision or non-positive for width, an 308 // exception of type format_error is thrown. 309 // 310 // Validate whether the arguments are integrals. 311 if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) { 312 // TODO FMT Remove this when parser v1 has been phased out. 313 if (__formatter.__width_needs_substitution()) 314 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__width)); 315 316 if constexpr (_HasPrecision) 317 if (__formatter.__precision_needs_substitution()) 318 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision)); 319 } else { 320 if (__formatter.__parser_.__width_as_arg_) 321 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); 322 323 if constexpr (_HasPrecision) 324 if (__formatter.__parser_.__precision_as_arg_) 325 __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); 326 } 327} 328 329template <class _CharT> 330_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx, 331 __compile_time_basic_format_context<_CharT>& __ctx, 332 __arg_t __type) { 333 switch (__type) { 334 case __arg_t::__none: 335 __throw_format_error("Invalid argument"); 336 case __arg_t::__boolean: 337 return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 338 case __arg_t::__char_type: 339 return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 340 case __arg_t::__int: 341 return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 342 case __arg_t::__long_long: 343 return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 344 case __arg_t::__i128: 345# ifndef _LIBCPP_HAS_NO_INT128 346 return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 347# else 348 __throw_format_error("Invalid argument"); 349# endif 350 return; 351 case __arg_t::__unsigned: 352 return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 353 case __arg_t::__unsigned_long_long: 354 return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 355 case __arg_t::__u128: 356# ifndef _LIBCPP_HAS_NO_INT128 357 return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 358# else 359 __throw_format_error("Invalid argument"); 360# endif 361 return; 362 case __arg_t::__float: 363 return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 364 case __arg_t::__double: 365 return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 366 case __arg_t::__long_double: 367 return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 368 case __arg_t::__const_char_type_ptr: 369 return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 370 case __arg_t::__string_view: 371 return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 372 case __arg_t::__ptr: 373 return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 374 case __arg_t::__handle: 375 __throw_format_error("Handle should use __compile_time_validate_handle_argument"); 376 } 377 __throw_format_error("Invalid argument"); 378} 379 380template <class _CharT, class _ParseCtx, class _Ctx> 381_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 382__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 383 _ParseCtx& __parse_ctx, _Ctx& __ctx) { 384 __format::__parse_number_result __r = 385 __format::__parse_arg_id(__begin, __end, __parse_ctx); 386 387 bool __parse = *__r.__ptr == _CharT(':'); 388 switch (*__r.__ptr) { 389 case _CharT(':'): 390 // The arg-id has a format-specifier, advance the input to the format-spec. 391 __parse_ctx.advance_to(__r.__ptr + 1); 392 break; 393 case _CharT('}'): 394 // The arg-id has no format-specifier. 395 __parse_ctx.advance_to(__r.__ptr); 396 break; 397 default: 398 __throw_format_error( 399 "The replacement field arg-id should terminate at a ':' or '}'"); 400 } 401 402 if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 403 __arg_t __type = __ctx.arg(__r.__value); 404 if (__type == __arg_t::__handle) 405 __ctx.__handle(__r.__value).__parse(__parse_ctx); 406 else 407 __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 408 } else 409 _VSTD::visit_format_arg( 410 [&](auto __arg) { 411 if constexpr (same_as<decltype(__arg), monostate>) 412 __throw_format_error("Argument index out of bounds"); 413 else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 414 __arg.format(__parse_ctx, __ctx); 415 else { 416 formatter<decltype(__arg), _CharT> __formatter; 417 if (__parse) 418 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 419 __ctx.advance_to(__formatter.format(__arg, __ctx)); 420 } 421 }, 422 __ctx.arg(__r.__value)); 423 424 __begin = __parse_ctx.begin(); 425 if (__begin == __end || *__begin != _CharT('}')) 426 __throw_format_error("The replacement field misses a terminating '}'"); 427 428 return ++__begin; 429} 430 431template <class _ParseCtx, class _Ctx> 432_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator 433__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 434 using _CharT = typename _ParseCtx::char_type; 435 static_assert(same_as<typename _Ctx::char_type, _CharT>); 436 437 const _CharT* __begin = __parse_ctx.begin(); 438 const _CharT* __end = __parse_ctx.end(); 439 typename _Ctx::iterator __out_it = __ctx.out(); 440 while (__begin != __end) { 441 switch (*__begin) { 442 case _CharT('{'): 443 ++__begin; 444 if (__begin == __end) 445 __throw_format_error("The format string terminates at a '{'"); 446 447 if (*__begin != _CharT('{')) [[likely]] { 448 __ctx.advance_to(_VSTD::move(__out_it)); 449 __begin = 450 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 451 __out_it = __ctx.out(); 452 453 // The output is written and __begin points to the next character. So 454 // start the next iteration. 455 continue; 456 } 457 // The string is an escape character. 458 break; 459 460 case _CharT('}'): 461 ++__begin; 462 if (__begin == __end || *__begin != _CharT('}')) 463 __throw_format_error( 464 "The format string contains an invalid escape sequence"); 465 466 break; 467 } 468 469 // Copy the character to the output verbatim. 470 *__out_it++ = *__begin++; 471 } 472 return __out_it; 473} 474 475} // namespace __format 476 477template <class _CharT, class... _Args> 478struct _LIBCPP_TEMPLATE_VIS basic_format_string { 479 template <class _Tp> 480 requires convertible_to<const _Tp&, basic_string_view<_CharT>> 481 consteval basic_format_string(const _Tp& __str) : __str_{__str} { 482 __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 483 _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 484 } 485 486 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { 487 return __str_; 488 } 489 490private: 491 basic_string_view<_CharT> __str_; 492 493 using _Context = __format::__compile_time_basic_format_context<_CharT>; 494 495 static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 496 __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 497 498 // TODO FMT remove this work-around when the AIX ICE has been resolved. 499# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 500 template <class _Tp> 501 static constexpr __format::__compile_time_handle<_CharT> __get_handle() { 502 __format::__compile_time_handle<_CharT> __handle; 503 if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 504 __handle.template __enable<_Tp>(); 505 506 return __handle; 507 } 508 509 static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ 510 __get_handle<_Args>()...}; 511# else 512 static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 513 using _Tp = remove_cvref_t<_Args>; 514 __format::__compile_time_handle<_CharT> __handle; 515 if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 516 __handle.template __enable<_Tp>(); 517 518 return __handle; 519 }()...}; 520# endif 521}; 522 523template <class... _Args> 524using format_string = basic_format_string<char, type_identity_t<_Args>...>; 525 526#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 527template <class... _Args> 528using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; 529#endif 530 531template <class _OutIt, class _CharT, class _FormatOutIt> 532requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 533 __vformat_to( 534 _OutIt __out_it, basic_string_view<_CharT> __fmt, 535 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 536 if constexpr (same_as<_OutIt, _FormatOutIt>) 537 return _VSTD::__format::__vformat_to( 538 basic_format_parse_context{__fmt, __args.__size()}, 539 _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 540 else { 541 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 542 _VSTD::__format::__vformat_to( 543 basic_format_parse_context{__fmt, __args.__size()}, 544 _VSTD::__format_context_create(__buffer.make_output_iterator(), 545 __args)); 546 return _VSTD::move(__buffer).out(); 547 } 548} 549 550// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 551// https://reviews.llvm.org/D110499#inline-1180704 552// TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 553template <output_iterator<const char&> _OutIt> 554_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 555vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 556 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 557} 558 559#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 560template <output_iterator<const wchar_t&> _OutIt> 561_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 562vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 563 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 564} 565#endif 566 567template <output_iterator<const char&> _OutIt, class... _Args> 568_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 569format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { 570 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), 571 _VSTD::make_format_args(__args...)); 572} 573 574#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 575template <output_iterator<const wchar_t&> _OutIt, class... _Args> 576_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 577format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { 578 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), 579 _VSTD::make_wformat_args(__args...)); 580} 581#endif 582 583_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 584vformat(string_view __fmt, format_args __args) { 585 string __res; 586 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 587 return __res; 588} 589 590#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 591_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 592vformat(wstring_view __fmt, wformat_args __args) { 593 wstring __res; 594 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 595 return __res; 596} 597#endif 598 599template <class... _Args> 600_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, 601 _Args&&... __args) { 602 return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); 603} 604 605#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 606template <class... _Args> 607_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 608format(wformat_string<_Args...> __fmt, _Args&&... __args) { 609 return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); 610} 611#endif 612 613template <class _Context, class _OutIt, class _CharT> 614_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 615 basic_string_view<_CharT> __fmt, 616 basic_format_args<_Context> __args) { 617 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 618 _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 619 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 620 return _VSTD::move(__buffer).result(); 621} 622 623template <output_iterator<const char&> _OutIt, class... _Args> 624_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 625format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { 626 return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); 627} 628 629#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 630template <output_iterator<const wchar_t&> _OutIt, class... _Args> 631_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 632format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, 633 _Args&&... __args) { 634 return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); 635} 636#endif 637 638template <class _CharT> 639_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 640 __format::__formatted_size_buffer<_CharT> __buffer; 641 _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 642 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 643 return _VSTD::move(__buffer).result(); 644} 645 646template <class... _Args> 647_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 648formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { 649 return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); 650} 651 652#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 653template <class... _Args> 654_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 655formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { 656 return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); 657} 658#endif 659 660#ifndef _LIBCPP_HAS_NO_LOCALIZATION 661 662template <class _OutIt, class _CharT, class _FormatOutIt> 663requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 664 __vformat_to( 665 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 666 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 667 if constexpr (same_as<_OutIt, _FormatOutIt>) 668 return _VSTD::__format::__vformat_to( 669 basic_format_parse_context{__fmt, __args.__size()}, 670 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 671 _VSTD::move(__loc))); 672 else { 673 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 674 _VSTD::__format::__vformat_to( 675 basic_format_parse_context{__fmt, __args.__size()}, 676 _VSTD::__format_context_create(__buffer.make_output_iterator(), 677 __args, _VSTD::move(__loc))); 678 return _VSTD::move(__buffer).out(); 679 } 680} 681 682template <output_iterator<const char&> _OutIt> 683_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 684 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 685 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 686 __args); 687} 688 689#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 690template <output_iterator<const wchar_t&> _OutIt> 691_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 692 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 693 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 694 __args); 695} 696#endif 697 698template <output_iterator<const char&> _OutIt, class... _Args> 699_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 700format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 701 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), 702 _VSTD::make_format_args(__args...)); 703} 704 705#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 706template <output_iterator<const wchar_t&> _OutIt, class... _Args> 707_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 708format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 709 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), 710 _VSTD::make_wformat_args(__args...)); 711} 712#endif 713 714_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 715vformat(locale __loc, string_view __fmt, format_args __args) { 716 string __res; 717 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 718 __args); 719 return __res; 720} 721 722#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 723_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 724vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 725 wstring __res; 726 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 727 __args); 728 return __res; 729} 730#endif 731 732template <class... _Args> 733_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, 734 format_string<_Args...> __fmt, 735 _Args&&... __args) { 736 return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), 737 _VSTD::make_format_args(__args...)); 738} 739 740#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 741template <class... _Args> 742_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 743format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 744 return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), 745 _VSTD::make_wformat_args(__args...)); 746} 747#endif 748 749template <class _Context, class _OutIt, class _CharT> 750_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 751 locale __loc, basic_string_view<_CharT> __fmt, 752 basic_format_args<_Context> __args) { 753 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 754 _VSTD::__format::__vformat_to( 755 basic_format_parse_context{__fmt, __args.__size()}, 756 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 757 return _VSTD::move(__buffer).result(); 758} 759 760template <output_iterator<const char&> _OutIt, class... _Args> 761_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 762format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, 763 _Args&&... __args) { 764 return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), 765 _VSTD::make_format_args(__args...)); 766} 767 768#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 769template <output_iterator<const wchar_t&> _OutIt, class... _Args> 770_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 771format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, 772 _Args&&... __args) { 773 return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), 774 _VSTD::make_wformat_args(__args...)); 775} 776#endif 777 778template <class _CharT> 779_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 780 __format::__formatted_size_buffer<_CharT> __buffer; 781 _VSTD::__format::__vformat_to( 782 basic_format_parse_context{__fmt, __args.__size()}, 783 _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 784 return _VSTD::move(__buffer).result(); 785} 786 787template <class... _Args> 788_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 789formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 790 return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); 791} 792 793#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 794template <class... _Args> 795_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 796formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 797 return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); 798} 799#endif 800 801#endif // _LIBCPP_HAS_NO_LOCALIZATION 802 803#endif //_LIBCPP_STD_VER > 17 804 805_LIBCPP_END_NAMESPACE_STD 806 807#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 808 809#endif // _LIBCPP_FORMAT 810