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