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