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( 192 basic_format_parse_context<_CharT>& __parse_ctx, 193 __compile_time_basic_format_context<_CharT>& __ctx, 194 __arg_t __type) { 195 switch (__type) { 196 case __arg_t::__none: 197 std::__throw_format_error("Invalid argument"); 198 case __arg_t::__boolean: 199 return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 200 case __arg_t::__char_type: 201 return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 202 case __arg_t::__int: 203 return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 204 case __arg_t::__long_long: 205 return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 206 case __arg_t::__i128: 207 # ifndef _LIBCPP_HAS_NO_INT128 208 return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 209 # else 210 std::__throw_format_error("Invalid argument"); 211 # endif 212 return; 213 case __arg_t::__unsigned: 214 return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 215 case __arg_t::__unsigned_long_long: 216 return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 217 case __arg_t::__u128: 218 # ifndef _LIBCPP_HAS_NO_INT128 219 return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 220 # else 221 std::__throw_format_error("Invalid argument"); 222 # endif 223 return; 224 case __arg_t::__float: 225 return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 226 case __arg_t::__double: 227 return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 228 case __arg_t::__long_double: 229 return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 230 case __arg_t::__const_char_type_ptr: 231 return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 232 case __arg_t::__string_view: 233 return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 234 case __arg_t::__ptr: 235 return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 236 case __arg_t::__handle: 237 std::__throw_format_error("Handle should use __compile_time_validate_handle_argument"); 238 } 239 std::__throw_format_error("Invalid argument"); 240 } 241 242 template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx> 243 _LIBCPP_HIDE_FROM_ABI constexpr _Iterator 244 __handle_replacement_field(_Iterator __begin, _Iterator __end, _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 std::__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 __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 298 using _CharT = typename _ParseCtx::char_type; 299 static_assert(same_as<typename _Ctx::char_type, _CharT>); 300 301 auto __begin = __parse_ctx.begin(); 302 auto __end = __parse_ctx.end(); 303 typename _Ctx::iterator __out_it = __ctx.out(); 304 while (__begin != __end) { 305 switch (*__begin) { 306 case _CharT('{'): 307 ++__begin; 308 if (__begin == __end) 309 std::__throw_format_error("The format string terminates at a '{'"); 310 311 if (*__begin != _CharT('{')) [[likely]] { 312 __ctx.advance_to(std::move(__out_it)); 313 __begin = __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 314 __out_it = __ctx.out(); 315 316 // The output is written and __begin points to the next character. So 317 // start the next iteration. 318 continue; 319 } 320 // The string is an escape character. 321 break; 322 323 case _CharT('}'): 324 ++__begin; 325 if (__begin == __end || *__begin != _CharT('}')) 326 std::__throw_format_error("The format string contains an invalid escape sequence"); 327 328 break; 329 } 330 331 // Copy the character to the output verbatim. 332 *__out_it++ = *__begin++; 333 } 334 return __out_it; 335 } 336 337 } // namespace __format 338 339 # if _LIBCPP_STD_VER >= 26 340 template <class _CharT> 341 struct _LIBCPP_TEMPLATE_VIS __runtime_format_string { 342 private: 343 basic_string_view<_CharT> __str_; 344 345 template <class _Cp, class... _Args> 346 friend struct _LIBCPP_TEMPLATE_VIS basic_format_string; 347 348 public: 349 _LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {} 350 351 __runtime_format_string(const __runtime_format_string&) = delete; 352 __runtime_format_string& operator=(const __runtime_format_string&) = delete; 353 }; 354 355 _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; } 356 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 357 _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept { 358 return __fmt; 359 } 360 # endif 361 # endif //_LIBCPP_STD_VER >= 26 362 363 template <class _CharT, class... _Args> 364 struct _LIBCPP_TEMPLATE_VIS basic_format_string { 365 template <class _Tp> 366 requires convertible_to<const _Tp&, basic_string_view<_CharT>> 367 consteval basic_format_string(const _Tp& __str) : __str_{__str} { 368 __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 369 _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 370 } 371 372 _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; } 373 # if _LIBCPP_STD_VER >= 26 374 _LIBCPP_HIDE_FROM_ABI basic_format_string(__runtime_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {} 375 # endif 376 377 private: 378 basic_string_view<_CharT> __str_; 379 380 using _Context = __format::__compile_time_basic_format_context<_CharT>; 381 382 static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 383 __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 384 385 static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 386 using _Tp = remove_cvref_t<_Args>; 387 __format::__compile_time_handle<_CharT> __handle; 388 if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 389 __handle.template __enable<_Tp>(); 390 391 return __handle; 392 }()...}; 393 }; 394 395 template <class... _Args> 396 using format_string = basic_format_string<char, type_identity_t<_Args>...>; 397 398 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 399 template <class... _Args> 400 using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; 401 # endif 402 403 template <class _OutIt, class _CharT, class _FormatOutIt> 404 requires(output_iterator<_OutIt, const _CharT&>) 405 _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it, 406 basic_string_view<_CharT> __fmt, 407 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 408 if constexpr (same_as<_OutIt, _FormatOutIt>) 409 return std::__format::__vformat_to( 410 basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args)); 411 else { 412 __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)}; 413 std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 414 std::__format_context_create(__buffer.__make_output_iterator(), __args)); 415 return std::move(__buffer).__out_it(); 416 } 417 } 418 419 // The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 420 // https://reviews.llvm.org/D110499#inline-1180704 421 // TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 422 template <output_iterator<const char&> _OutIt> 423 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 424 return std::__vformat_to(std::move(__out_it), __fmt, __args); 425 } 426 427 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 428 template <output_iterator<const wchar_t&> _OutIt> 429 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 430 vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 431 return std::__vformat_to(std::move(__out_it), __fmt, __args); 432 } 433 # endif 434 435 template <output_iterator<const char&> _OutIt, class... _Args> 436 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 437 format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { 438 return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_format_args(__args...)); 439 } 440 441 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 442 template <output_iterator<const wchar_t&> _OutIt, class... _Args> 443 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 444 format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { 445 return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_wformat_args(__args...)); 446 } 447 # endif 448 449 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 450 // fires too eagerly, see http://llvm.org/PR61563. 451 template <class = void> 452 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string 453 vformat(string_view __fmt, format_args __args) { 454 string __res; 455 std::vformat_to(std::back_inserter(__res), __fmt, __args); 456 return __res; 457 } 458 459 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 460 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 461 // fires too eagerly, see http://llvm.org/PR61563. 462 template <class = void> 463 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring 464 vformat(wstring_view __fmt, wformat_args __args) { 465 wstring __res; 466 std::vformat_to(std::back_inserter(__res), __fmt, __args); 467 return __res; 468 } 469 # endif 470 471 template <class... _Args> 472 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string 473 format(format_string<_Args...> __fmt, _Args&&... __args) { 474 return std::vformat(__fmt.get(), std::make_format_args(__args...)); 475 } 476 477 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 478 template <class... _Args> 479 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring 480 format(wformat_string<_Args...> __fmt, _Args&&... __args) { 481 return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); 482 } 483 # endif 484 485 template <class _Context, class _OutIt, class _CharT> 486 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 487 __vformat_to_n(_OutIt __out_it, 488 iter_difference_t<_OutIt> __n, 489 basic_string_view<_CharT> __fmt, 490 basic_format_args<_Context> __args) { 491 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n}; 492 std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 493 std::__format_context_create(__buffer.__make_output_iterator(), __args)); 494 return std::move(__buffer).__result(); 495 } 496 497 template <output_iterator<const char&> _OutIt, class... _Args> 498 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 499 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { 500 return std::__vformat_to_n<format_context>(std::move(__out_it), __n, __fmt.get(), std::make_format_args(__args...)); 501 } 502 503 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 504 template <output_iterator<const wchar_t&> _OutIt, class... _Args> 505 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 506 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { 507 return std::__vformat_to_n<wformat_context>(std::move(__out_it), __n, __fmt.get(), std::make_wformat_args(__args...)); 508 } 509 # endif 510 511 template <class _CharT> 512 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 513 __format::__formatted_size_buffer<_CharT> __buffer; 514 std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 515 std::__format_context_create(__buffer.__make_output_iterator(), __args)); 516 return std::move(__buffer).__result(); 517 } 518 519 template <class... _Args> 520 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 521 formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { 522 return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)}); 523 } 524 525 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 526 template <class... _Args> 527 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 528 formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { 529 return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); 530 } 531 # endif 532 533 # ifndef _LIBCPP_HAS_NO_LOCALIZATION 534 535 template <class _OutIt, class _CharT, class _FormatOutIt> 536 requires(output_iterator<_OutIt, const _CharT&>) 537 _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to( 538 _OutIt __out_it, 539 locale __loc, 540 basic_string_view<_CharT> __fmt, 541 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 542 if constexpr (same_as<_OutIt, _FormatOutIt>) 543 return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 544 std::__format_context_create(std::move(__out_it), __args, std::move(__loc))); 545 else { 546 __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)}; 547 std::__format::__vformat_to( 548 basic_format_parse_context{__fmt, __args.__size()}, 549 std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 550 return std::move(__buffer).__out_it(); 551 } 552 } 553 554 template <output_iterator<const char&> _OutIt> 555 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 556 vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 557 return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args); 558 } 559 560 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 561 template <output_iterator<const wchar_t&> _OutIt> 562 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 563 vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 564 return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args); 565 } 566 # endif 567 568 template <output_iterator<const char&> _OutIt, class... _Args> 569 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 570 format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 571 return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 572 } 573 574 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 575 template <output_iterator<const wchar_t&> _OutIt, class... _Args> 576 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 577 format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 578 return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 579 } 580 # endif 581 582 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 583 // fires too eagerly, see http://llvm.org/PR61563. 584 template <class = void> 585 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string 586 vformat(locale __loc, string_view __fmt, format_args __args) { 587 string __res; 588 std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); 589 return __res; 590 } 591 592 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 593 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 594 // fires too eagerly, see http://llvm.org/PR61563. 595 template <class = void> 596 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring 597 vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 598 wstring __res; 599 std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); 600 return __res; 601 } 602 # endif 603 604 template <class... _Args> 605 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string 606 format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 607 return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 608 } 609 610 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 611 template <class... _Args> 612 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring 613 format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 614 return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 615 } 616 # endif 617 618 template <class _Context, class _OutIt, class _CharT> 619 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n( 620 _OutIt __out_it, 621 iter_difference_t<_OutIt> __n, 622 locale __loc, 623 basic_string_view<_CharT> __fmt, 624 basic_format_args<_Context> __args) { 625 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n}; 626 std::__format::__vformat_to( 627 basic_format_parse_context{__fmt, __args.__size()}, 628 std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 629 return std::move(__buffer).__result(); 630 } 631 632 template <output_iterator<const char&> _OutIt, class... _Args> 633 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n( 634 _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 635 return std::__vformat_to_n<format_context>( 636 std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 637 } 638 639 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 640 template <output_iterator<const wchar_t&> _OutIt, class... _Args> 641 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n( 642 _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 643 return std::__vformat_to_n<wformat_context>( 644 std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 645 } 646 # endif 647 648 template <class _CharT> 649 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 650 __format::__formatted_size_buffer<_CharT> __buffer; 651 std::__format::__vformat_to( 652 basic_format_parse_context{__fmt, __args.__size()}, 653 std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 654 return std::move(__buffer).__result(); 655 } 656 657 template <class... _Args> 658 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 659 formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 660 return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)}); 661 } 662 663 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 664 template <class... _Args> 665 _LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 666 formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 667 return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); 668 } 669 # endif 670 671 # endif // _LIBCPP_HAS_NO_LOCALIZATION 672 673 #endif //_LIBCPP_STD_VER >= 20 674 675 _LIBCPP_END_NAMESPACE_STD 676 677 #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS 678