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