1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_FORMAT 11#define _LIBCPP_FORMAT 12 13/* 14 15namespace std { 16 // [format.context], class template basic_format_context 17 template<class Out, class charT> 18 class basic_format_context { 19 basic_format_args<basic_format_context> args_; // exposition only 20 Out out_; // exposition only 21 22 public: 23 using iterator = Out; 24 using char_type = charT; 25 template<class T> using formatter_type = formatter<T, charT>; 26 27 basic_format_arg<basic_format_context> arg(size_t id) const; 28 std::locale locale(); 29 30 iterator out(); 31 void advance_to(iterator it); 32 }; 33 using format_context = basic_format_context<unspecified, char>; 34 using wformat_context = basic_format_context<unspecified, wchar_t>; 35 36 // [format.args], class template basic_format_args 37 template<class Context> 38 class basic_format_args { 39 size_t size_; // exposition only 40 const basic_format_arg<Context>* data_; // exposition only 41 42 public: 43 basic_format_args() noexcept; 44 45 template<class... Args> 46 basic_format_args(const format-arg-store<Context, Args...>& store) noexcept; 47 48 basic_format_arg<Context> get(size_t i) const noexcept; 49 }; 50 using format_args = basic_format_args<format_context>; 51 using wformat_args = basic_format_args<wformat_context>; 52 53 54 // [format.functions], formatting functions 55 template<class... Args> 56 string format(string_view fmt, const Args&... args); 57 template<class... Args> 58 wstring format(wstring_view fmt, const Args&... args); 59 template<class... Args> 60 string format(const locale& loc, string_view fmt, const Args&... args); 61 template<class... Args> 62 wstring format(const locale& loc, wstring_view fmt, const Args&... args); 63 64 string vformat(string_view fmt, format_args args); 65 wstring vformat(wstring_view fmt, wformat_args args); 66 string vformat(const locale& loc, string_view fmt, format_args args); 67 wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); 68 69 template<class Out, class... Args> 70 Out format_to(Out out, string_view fmt, const Args&... args); 71 template<class Out, class... Args> 72 Out format_to(Out out, wstring_view fmt, const Args&... args); 73 template<class Out, class... Args> 74 Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args); 75 template<class Out, class... Args> 76 Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args); 77 78 template<class Out> 79 Out vformat_to(Out out, string_view fmt, format_args args); 80 template<class Out> 81 Out vformat_to(Out out, wstring_view fmt, wformat_args args); 82 template<class Out> 83 Out vformat_to(Out out, const locale& loc, string_view fmt, 84 format_args char> args); 85 template<class Out> 86 Out vformat_to(Out out, const locale& loc, wstring_view fmt, 87 wformat_args args); 88 89 template<class Out> struct format_to_n_result { 90 Out out; 91 iter_difference_t<Out> size; 92 }; 93 94 template<class Out, class... Args> 95 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 96 string_view fmt, const Args&... args); 97 template<class Out, class... Args> 98 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 99 wstring_view fmt, const Args&... args); 100 template<class Out, class... Args> 101 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 102 const locale& loc, string_view fmt, 103 const Args&... args); 104 template<class Out, class... Args> 105 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 106 const locale& loc, wstring_view fmt, 107 const Args&... args); 108 109 template<class... Args> 110 size_t formatted_size(string_view fmt, const Args&... args); 111 template<class... Args> 112 size_t formatted_size(wstring_view fmt, const Args&... args); 113 template<class... Args> 114 size_t formatted_size(const locale& loc, string_view fmt, const Args&... args); 115 template<class... Args> 116 size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args); 117 118 // [format.formatter], formatter 119 template<> struct formatter<char, char>; 120 template<> struct formatter<char, wchar_t>; 121 template<> struct formatter<wchar_t, wchar_t>; 122 123 template<> struct formatter<charT*, charT>; 124 template<> struct formatter<const charT*, charT>; 125 template<size_t N> struct formatter<const charT[N], charT>; 126 template<class traits, class Allocator> 127 struct formatter<basic_string<charT, traits, Allocator>, charT>; 128 template<class traits> 129 struct formatter<basic_string_view<charT, traits>, charT>; 130 131 // [format.parse.ctx], class template basic_format_parse_context 132 template<class charT> 133 class basic_format_parse_context { 134 public: 135 using char_type = charT; 136 using const_iterator = typename basic_string_view<charT>::const_iterator; 137 using iterator = const_iterator; 138 139 private: 140 iterator begin_; // exposition only 141 iterator end_; // exposition only 142 enum indexing { unknown, manual, automatic }; // exposition only 143 indexing indexing_; // exposition only 144 size_t next_arg_id_; // exposition only 145 size_t num_args_; // exposition only 146 147 public: 148 constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt, 149 size_t num_args = 0) noexcept; 150 basic_format_parse_context(const basic_format_parse_context&) = delete; 151 basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; 152 153 constexpr const_iterator begin() const noexcept; 154 constexpr const_iterator end() const noexcept; 155 constexpr void advance_to(const_iterator it); 156 157 constexpr size_t next_arg_id(); 158 constexpr void check_arg_id(size_t id); 159 }; 160 using format_parse_context = basic_format_parse_context<char>; 161 using wformat_parse_context = basic_format_parse_context<wchar_t>; 162 163 // [format.arguments], arguments 164 // [format.arg], class template basic_format_arg 165 template<class Context> 166 class basic_format_arg { 167 public: 168 class handle; 169 170 private: 171 using char_type = typename Context::char_type; // exposition only 172 173 variant<monostate, bool, char_type, 174 int, unsigned int, long long int, unsigned long long int, 175 float, double, long double, 176 const char_type*, basic_string_view<char_type>, 177 const void*, handle> value; // exposition only 178 179 template<class T> explicit basic_format_arg(const T& v) noexcept; // exposition only 180 explicit basic_format_arg(float n) noexcept; // exposition only 181 explicit basic_format_arg(double n) noexcept; // exposition only 182 explicit basic_format_arg(long double n) noexcept; // exposition only 183 explicit basic_format_arg(const char_type* s); // exposition only 184 185 template<class traits> 186 explicit basic_format_arg( 187 basic_string_view<char_type, traits> s) noexcept; // exposition only 188 189 template<class traits, class Allocator> 190 explicit basic_format_arg( 191 const basic_string<char_type, traits, Allocator>& s) noexcept; // exposition only 192 193 explicit basic_format_arg(nullptr_t) noexcept; // exposition only 194 195 template<class T> 196 explicit basic_format_arg(const T* p) noexcept; // exposition only 197 198 public: 199 basic_format_arg() noexcept; 200 201 explicit operator bool() const noexcept; 202 }; 203 204 template<class Visitor, class Context> 205 see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); 206 207 // [format.arg.store], class template format-arg-store 208 template<class Context, class... Args> 209 struct format-arg-store { // exposition only 210 array<basic_format_arg<Context>, sizeof...(Args)> args; 211 }; 212 213 template<class Context = format_context, class... Args> 214 format-arg-store<Context, Args...> 215 make_format_args(const Args&... args); 216 template<class... Args> 217 format-arg-store<wformat_context, Args...> 218 make_wformat_args(const Args&... args); 219 220 // [format.error], class format_error 221 class format_error : public runtime_error { 222 public: 223 explicit format_error(const string& what_arg); 224 explicit format_error(const char* what_arg); 225 }; 226 227 // [format.parse.ctx], class template basic_format_parse_context 228 template<class charT> 229 class basic_format_parse_context { 230 public: 231 using char_type = charT; 232 using const_iterator = typename basic_string_view<charT>::const_iterator; 233 using iterator = const_iterator; 234 235 private: 236 iterator begin_; // exposition only 237 iterator end_; // exposition only 238 enum indexing { unknown, manual, automatic }; // exposition only 239 indexing indexing_; // exposition only 240 size_t next_arg_id_; // exposition only 241 size_t num_args_; // exposition only 242 243 public: 244 constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt, 245 size_t num_args = 0) noexcept; 246 basic_format_parse_context(const basic_format_parse_context&) = delete; 247 basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; 248 249 constexpr const_iterator begin() const noexcept; 250 constexpr const_iterator end() const noexcept; 251 constexpr void advance_to(const_iterator it); 252 253 constexpr size_t next_arg_id(); 254 constexpr void check_arg_id(size_t id); 255 }; 256 using format_parse_context = basic_format_parse_context<char>; 257 using wformat_parse_context = basic_format_parse_context<wchar_t>; 258} 259 260*/ 261 262// Make sure all feature-test macros are available. 263#include <version> 264// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES. 265#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 266 267#include <__config> 268#include <__debug> 269#include <__format/format_arg.h> 270#include <__format/format_args.h> 271#include <__format/format_context.h> 272#include <__format/format_error.h> 273#include <__format/format_fwd.h> 274#include <__format/format_parse_context.h> 275#include <__format/format_string.h> 276#include <__format/format_to_n_result.h> 277#include <__format/formatter.h> 278#include <__format/formatter_bool.h> 279#include <__format/formatter_char.h> 280#include <__format/formatter_floating_point.h> 281#include <__format/formatter_integer.h> 282#include <__format/formatter_pointer.h> 283#include <__format/formatter_string.h> 284#include <__format/parser_std_format_spec.h> 285#include <__variant/monostate.h> 286#include <array> 287#include <concepts> 288#include <string> 289#include <string_view> 290#include <type_traits> 291 292#ifndef _LIBCPP_HAS_NO_LOCALIZATION 293#include <locale> 294#endif 295 296#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 297#pragma GCC system_header 298#endif 299 300_LIBCPP_PUSH_MACROS 301#include <__undef_macros> 302 303_LIBCPP_BEGIN_NAMESPACE_STD 304 305#if _LIBCPP_STD_VER > 17 306 307// TODO FMT Remove this once we require compilers with proper C++20 support. 308// If the compiler has no concepts support, the format header will be disabled. 309// Without concepts support enable_if needs to be used and that too much effort 310// to support compilers with partial C++20 support. 311#if !defined(_LIBCPP_HAS_NO_CONCEPTS) 312 313// TODO FMT Move the implementation in this file to its own granular headers. 314 315// TODO FMT Evaluate which templates should be external templates. This 316// improves the efficiency of the header. However since the header is still 317// under heavy development and not all classes are stable it makes no sense 318// to do this optimization now. 319 320using format_args = basic_format_args<format_context>; 321#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 322using wformat_args = basic_format_args<wformat_context>; 323#endif 324 325template <class _Context, class... _Args> 326struct _LIBCPP_TEMPLATE_VIS __format_arg_store { 327 // TODO FMT Use a built-in array. 328 array<basic_format_arg<_Context>, sizeof...(_Args)> __args; 329}; 330 331template <class _Context = format_context, class... _Args> 332_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> 333make_format_args(const _Args&... __args) { 334 return {basic_format_arg<_Context>(__args)...}; 335} 336 337#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 338template <class... _Args> 339_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> 340make_wformat_args(const _Args&... __args) { 341 return _VSTD::make_format_args<wformat_context>(__args...); 342} 343#endif 344 345namespace __format { 346 347template <class _CharT, class _ParseCtx, class _Ctx> 348_LIBCPP_HIDE_FROM_ABI const _CharT* 349__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 350 _ParseCtx& __parse_ctx, _Ctx& __ctx) { 351 __format::__parse_number_result __r = 352 __format::__parse_arg_id(__begin, __end, __parse_ctx); 353 354 switch (*__r.__ptr) { 355 case _CharT(':'): 356 // The arg-id has a format-specifier, advance the input to the format-spec. 357 __parse_ctx.advance_to(__r.__ptr + 1); 358 break; 359 case _CharT('}'): 360 // The arg-id has no format-specifier. 361 __parse_ctx.advance_to(__r.__ptr); 362 break; 363 default: 364 __throw_format_error( 365 "The replacement field arg-id should terminate at a ':' or '}'"); 366 } 367 368 _VSTD::visit_format_arg( 369 [&](auto __arg) { 370 if constexpr (same_as<decltype(__arg), monostate>) 371 __throw_format_error("Argument index out of bounds"); 372 else { 373 formatter<decltype(__arg), _CharT> __formatter; 374 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 375 __ctx.advance_to(__formatter.format(__arg, __ctx)); 376 } 377 }, 378 __ctx.arg(__r.__value)); 379 380 __begin = __parse_ctx.begin(); 381 if (__begin == __end || *__begin != _CharT('}')) 382 __throw_format_error("The replacement field misses a terminating '}'"); 383 384 return ++__begin; 385} 386 387template <class _ParseCtx, class _Ctx> 388_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator 389__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 390 using _CharT = typename _ParseCtx::char_type; 391 static_assert(same_as<typename _Ctx::char_type, _CharT>); 392 393 const _CharT* __begin = __parse_ctx.begin(); 394 const _CharT* __end = __parse_ctx.end(); 395 typename _Ctx::iterator __out_it = __ctx.out(); 396 while (__begin != __end) { 397 switch (*__begin) { 398 case _CharT('{'): 399 ++__begin; 400 if (__begin == __end) 401 __throw_format_error("The format string terminates at a '{'"); 402 403 if (*__begin != _CharT('{')) [[likely]] { 404 __ctx.advance_to(_VSTD::move(__out_it)); 405 __begin = 406 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 407 __out_it = __ctx.out(); 408 409 // The output is written and __begin points to the next character. So 410 // start the next iteration. 411 continue; 412 } 413 // The string is an escape character. 414 break; 415 416 case _CharT('}'): 417 ++__begin; 418 if (__begin == __end || *__begin != _CharT('}')) 419 __throw_format_error( 420 "The format string contains an invalid escape sequence"); 421 422 break; 423 } 424 425 // Copy the character to the output verbatim. 426 *__out_it++ = *__begin++; 427 } 428 return __out_it; 429} 430 431} // namespace __format 432 433template <class _OutIt, class _CharT, class _FormatOutIt> 434requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 435 __vformat_to( 436 _OutIt __out_it, basic_string_view<_CharT> __fmt, 437 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 438 if constexpr (same_as<_OutIt, _FormatOutIt>) 439 return _VSTD::__format::__vformat_to( 440 basic_format_parse_context{__fmt, __args.__size()}, 441 _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 442 else { 443 basic_string<_CharT> __str; 444 _VSTD::__format::__vformat_to( 445 basic_format_parse_context{__fmt, __args.__size()}, 446 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args)); 447 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it)); 448 } 449} 450 451template <output_iterator<const char&> _OutIt> 452_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 453vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 454 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 455} 456 457#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 458template <output_iterator<const wchar_t&> _OutIt> 459_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 460vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 461 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 462} 463#endif 464 465template <output_iterator<const char&> _OutIt, class... _Args> 466_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 467format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) { 468 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 469 _VSTD::make_format_args(__args...)); 470} 471 472#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 473template <output_iterator<const wchar_t&> _OutIt, class... _Args> 474_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 475format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) { 476 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 477 _VSTD::make_wformat_args(__args...)); 478} 479#endif 480 481_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 482vformat(string_view __fmt, format_args __args) { 483 string __res; 484 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 485 return __res; 486} 487 488#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 489_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 490vformat(wstring_view __fmt, wformat_args __args) { 491 wstring __res; 492 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 493 return __res; 494} 495#endif 496 497template <class... _Args> 498_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 499format(string_view __fmt, const _Args&... __args) { 500 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 501} 502 503#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 504template <class... _Args> 505_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 506format(wstring_view __fmt, const _Args&... __args) { 507 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 508} 509#endif 510 511template <output_iterator<const char&> _OutIt, class... _Args> 512_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 513format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, 514 const _Args&... __args) { 515 // TODO FMT Improve PoC: using std::string is inefficient. 516 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 517 iter_difference_t<_OutIt> __s = __str.size(); 518 iter_difference_t<_OutIt> __m = 519 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 520 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 521 return {_VSTD::move(__out_it), __s}; 522} 523 524#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 525template <output_iterator<const wchar_t&> _OutIt, class... _Args> 526_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 527format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, 528 const _Args&... __args) { 529 // TODO FMT Improve PoC: using std::string is inefficient. 530 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 531 iter_difference_t<_OutIt> __s = __str.size(); 532 iter_difference_t<_OutIt> __m = 533 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 534 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 535 return {_VSTD::move(__out_it), __s}; 536} 537#endif 538 539template <class... _Args> 540_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 541formatted_size(string_view __fmt, const _Args&... __args) { 542 // TODO FMT Improve PoC: using std::string is inefficient. 543 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size(); 544} 545 546#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 547template <class... _Args> 548_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 549formatted_size(wstring_view __fmt, const _Args&... __args) { 550 // TODO FMT Improve PoC: using std::string is inefficient. 551 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size(); 552} 553#endif 554 555#ifndef _LIBCPP_HAS_NO_LOCALIZATION 556 557template <class _OutIt, class _CharT, class _FormatOutIt> 558requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 559 __vformat_to( 560 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 561 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 562 if constexpr (same_as<_OutIt, _FormatOutIt>) 563 return _VSTD::__format::__vformat_to( 564 basic_format_parse_context{__fmt, __args.__size()}, 565 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 566 _VSTD::move(__loc))); 567 else { 568 basic_string<_CharT> __str; 569 _VSTD::__format::__vformat_to( 570 basic_format_parse_context{__fmt, __args.__size()}, 571 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args, 572 _VSTD::move(__loc))); 573 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it)); 574 } 575} 576 577template <output_iterator<const char&> _OutIt> 578_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 579 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 580 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 581 __args); 582} 583 584#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 585template <output_iterator<const wchar_t&> _OutIt> 586_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 587 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 588 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 589 __args); 590} 591#endif 592 593template <output_iterator<const char&> _OutIt, class... _Args> 594_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 595 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) { 596 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 597 _VSTD::make_format_args(__args...)); 598} 599 600#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 601template <output_iterator<const wchar_t&> _OutIt, class... _Args> 602_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 603 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) { 604 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 605 _VSTD::make_wformat_args(__args...)); 606} 607#endif 608 609_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 610vformat(locale __loc, string_view __fmt, format_args __args) { 611 string __res; 612 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 613 __args); 614 return __res; 615} 616 617#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 618_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 619vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 620 wstring __res; 621 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 622 __args); 623 return __res; 624} 625#endif 626 627template <class... _Args> 628_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 629format(locale __loc, string_view __fmt, const _Args&... __args) { 630 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 631 _VSTD::make_format_args(__args...)); 632} 633 634#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 635template <class... _Args> 636_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 637format(locale __loc, wstring_view __fmt, const _Args&... __args) { 638 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 639 _VSTD::make_wformat_args(__args...)); 640} 641#endif 642 643template <output_iterator<const char&> _OutIt, class... _Args> 644_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 645format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 646 string_view __fmt, const _Args&... __args) { 647 // TODO FMT Improve PoC: using std::string is inefficient. 648 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 649 _VSTD::make_format_args(__args...)); 650 iter_difference_t<_OutIt> __s = __str.size(); 651 iter_difference_t<_OutIt> __m = 652 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 653 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 654 return {_VSTD::move(__out_it), __s}; 655} 656 657#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 658template <output_iterator<const wchar_t&> _OutIt, class... _Args> 659_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 660format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 661 wstring_view __fmt, const _Args&... __args) { 662 // TODO FMT Improve PoC: using std::string is inefficient. 663 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 664 _VSTD::make_wformat_args(__args...)); 665 iter_difference_t<_OutIt> __s = __str.size(); 666 iter_difference_t<_OutIt> __m = 667 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 668 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 669 return {_VSTD::move(__out_it), __s}; 670} 671#endif 672 673template <class... _Args> 674_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 675formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { 676 // TODO FMT Improve PoC: using std::string is inefficient. 677 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 678 _VSTD::make_format_args(__args...)) 679 .size(); 680} 681 682#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 683template <class... _Args> 684_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 685formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { 686 // TODO FMT Improve PoC: using std::string is inefficient. 687 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 688 _VSTD::make_wformat_args(__args...)) 689 .size(); 690} 691#endif 692 693#endif // _LIBCPP_HAS_NO_LOCALIZATION 694 695#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 696#endif //_LIBCPP_STD_VER > 17 697 698_LIBCPP_END_NAMESPACE_STD 699 700_LIBCPP_POP_MACROS 701 702#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 703 704#endif // _LIBCPP_FORMAT 705