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 if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 373 __arg.format(__parse_ctx, __ctx); 374 else { 375 formatter<decltype(__arg), _CharT> __formatter; 376 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 377 __ctx.advance_to(__formatter.format(__arg, __ctx)); 378 } 379 }, 380 __ctx.arg(__r.__value)); 381 382 __begin = __parse_ctx.begin(); 383 if (__begin == __end || *__begin != _CharT('}')) 384 __throw_format_error("The replacement field misses a terminating '}'"); 385 386 return ++__begin; 387} 388 389template <class _ParseCtx, class _Ctx> 390_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator 391__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 392 using _CharT = typename _ParseCtx::char_type; 393 static_assert(same_as<typename _Ctx::char_type, _CharT>); 394 395 const _CharT* __begin = __parse_ctx.begin(); 396 const _CharT* __end = __parse_ctx.end(); 397 typename _Ctx::iterator __out_it = __ctx.out(); 398 while (__begin != __end) { 399 switch (*__begin) { 400 case _CharT('{'): 401 ++__begin; 402 if (__begin == __end) 403 __throw_format_error("The format string terminates at a '{'"); 404 405 if (*__begin != _CharT('{')) [[likely]] { 406 __ctx.advance_to(_VSTD::move(__out_it)); 407 __begin = 408 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 409 __out_it = __ctx.out(); 410 411 // The output is written and __begin points to the next character. So 412 // start the next iteration. 413 continue; 414 } 415 // The string is an escape character. 416 break; 417 418 case _CharT('}'): 419 ++__begin; 420 if (__begin == __end || *__begin != _CharT('}')) 421 __throw_format_error( 422 "The format string contains an invalid escape sequence"); 423 424 break; 425 } 426 427 // Copy the character to the output verbatim. 428 *__out_it++ = *__begin++; 429 } 430 return __out_it; 431} 432 433} // namespace __format 434 435template <class _OutIt, class _CharT, class _FormatOutIt> 436requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 437 __vformat_to( 438 _OutIt __out_it, basic_string_view<_CharT> __fmt, 439 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 440 if constexpr (same_as<_OutIt, _FormatOutIt>) 441 return _VSTD::__format::__vformat_to( 442 basic_format_parse_context{__fmt, __args.__size()}, 443 _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 444 else { 445 basic_string<_CharT> __str; 446 _VSTD::__format::__vformat_to( 447 basic_format_parse_context{__fmt, __args.__size()}, 448 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args)); 449 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it)); 450 } 451} 452 453template <output_iterator<const char&> _OutIt> 454_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 455vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 456 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 457} 458 459#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 460template <output_iterator<const wchar_t&> _OutIt> 461_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 462vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 463 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 464} 465#endif 466 467template <output_iterator<const char&> _OutIt, class... _Args> 468_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 469format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) { 470 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 471 _VSTD::make_format_args(__args...)); 472} 473 474#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 475template <output_iterator<const wchar_t&> _OutIt, class... _Args> 476_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 477format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) { 478 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 479 _VSTD::make_wformat_args(__args...)); 480} 481#endif 482 483_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 484vformat(string_view __fmt, format_args __args) { 485 string __res; 486 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 487 return __res; 488} 489 490#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 491_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 492vformat(wstring_view __fmt, wformat_args __args) { 493 wstring __res; 494 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 495 return __res; 496} 497#endif 498 499template <class... _Args> 500_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 501format(string_view __fmt, const _Args&... __args) { 502 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 503} 504 505#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 506template <class... _Args> 507_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 508format(wstring_view __fmt, const _Args&... __args) { 509 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 510} 511#endif 512 513template <output_iterator<const char&> _OutIt, class... _Args> 514_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 515format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, 516 const _Args&... __args) { 517 // TODO FMT Improve PoC: using std::string is inefficient. 518 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 519 iter_difference_t<_OutIt> __s = __str.size(); 520 iter_difference_t<_OutIt> __m = 521 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 522 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 523 return {_VSTD::move(__out_it), __s}; 524} 525 526#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 527template <output_iterator<const wchar_t&> _OutIt, class... _Args> 528_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 529format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, 530 const _Args&... __args) { 531 // TODO FMT Improve PoC: using std::string is inefficient. 532 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 533 iter_difference_t<_OutIt> __s = __str.size(); 534 iter_difference_t<_OutIt> __m = 535 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 536 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 537 return {_VSTD::move(__out_it), __s}; 538} 539#endif 540 541template <class... _Args> 542_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 543formatted_size(string_view __fmt, const _Args&... __args) { 544 // TODO FMT Improve PoC: using std::string is inefficient. 545 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size(); 546} 547 548#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 549template <class... _Args> 550_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 551formatted_size(wstring_view __fmt, const _Args&... __args) { 552 // TODO FMT Improve PoC: using std::string is inefficient. 553 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size(); 554} 555#endif 556 557#ifndef _LIBCPP_HAS_NO_LOCALIZATION 558 559template <class _OutIt, class _CharT, class _FormatOutIt> 560requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 561 __vformat_to( 562 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 563 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 564 if constexpr (same_as<_OutIt, _FormatOutIt>) 565 return _VSTD::__format::__vformat_to( 566 basic_format_parse_context{__fmt, __args.__size()}, 567 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 568 _VSTD::move(__loc))); 569 else { 570 basic_string<_CharT> __str; 571 _VSTD::__format::__vformat_to( 572 basic_format_parse_context{__fmt, __args.__size()}, 573 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args, 574 _VSTD::move(__loc))); 575 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it)); 576 } 577} 578 579template <output_iterator<const char&> _OutIt> 580_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 581 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 582 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 583 __args); 584} 585 586#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 587template <output_iterator<const wchar_t&> _OutIt> 588_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 589 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 590 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 591 __args); 592} 593#endif 594 595template <output_iterator<const char&> _OutIt, class... _Args> 596_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 597 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) { 598 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 599 _VSTD::make_format_args(__args...)); 600} 601 602#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 603template <output_iterator<const wchar_t&> _OutIt, class... _Args> 604_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 605 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) { 606 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 607 _VSTD::make_wformat_args(__args...)); 608} 609#endif 610 611_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 612vformat(locale __loc, string_view __fmt, format_args __args) { 613 string __res; 614 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 615 __args); 616 return __res; 617} 618 619#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 620_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 621vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 622 wstring __res; 623 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 624 __args); 625 return __res; 626} 627#endif 628 629template <class... _Args> 630_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 631format(locale __loc, string_view __fmt, const _Args&... __args) { 632 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 633 _VSTD::make_format_args(__args...)); 634} 635 636#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 637template <class... _Args> 638_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 639format(locale __loc, wstring_view __fmt, const _Args&... __args) { 640 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 641 _VSTD::make_wformat_args(__args...)); 642} 643#endif 644 645template <output_iterator<const char&> _OutIt, class... _Args> 646_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 647format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 648 string_view __fmt, const _Args&... __args) { 649 // TODO FMT Improve PoC: using std::string is inefficient. 650 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 651 _VSTD::make_format_args(__args...)); 652 iter_difference_t<_OutIt> __s = __str.size(); 653 iter_difference_t<_OutIt> __m = 654 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 655 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 656 return {_VSTD::move(__out_it), __s}; 657} 658 659#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 660template <output_iterator<const wchar_t&> _OutIt, class... _Args> 661_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 662format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 663 wstring_view __fmt, const _Args&... __args) { 664 // TODO FMT Improve PoC: using std::string is inefficient. 665 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 666 _VSTD::make_wformat_args(__args...)); 667 iter_difference_t<_OutIt> __s = __str.size(); 668 iter_difference_t<_OutIt> __m = 669 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 670 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 671 return {_VSTD::move(__out_it), __s}; 672} 673#endif 674 675template <class... _Args> 676_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 677formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { 678 // TODO FMT Improve PoC: using std::string is inefficient. 679 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 680 _VSTD::make_format_args(__args...)) 681 .size(); 682} 683 684#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 685template <class... _Args> 686_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 687formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { 688 // TODO FMT Improve PoC: using std::string is inefficient. 689 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 690 _VSTD::make_wformat_args(__args...)) 691 .size(); 692} 693#endif 694 695#endif // _LIBCPP_HAS_NO_LOCALIZATION 696 697#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 698#endif //_LIBCPP_STD_VER > 17 699 700_LIBCPP_END_NAMESPACE_STD 701 702_LIBCPP_POP_MACROS 703 704#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 705 706#endif // _LIBCPP_FORMAT 707