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