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