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_string.h> 283#include <__format/parser_std_format_spec.h> 284#include <__variant/monostate.h> 285#include <array> 286#include <concepts> 287#include <string> 288#include <string_view> 289#include <type_traits> 290 291#ifndef _LIBCPP_HAS_NO_LOCALIZATION 292#include <locale> 293#endif 294 295#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 296#pragma GCC system_header 297#endif 298 299_LIBCPP_PUSH_MACROS 300#include <__undef_macros> 301 302_LIBCPP_BEGIN_NAMESPACE_STD 303 304#if _LIBCPP_STD_VER > 17 305 306// TODO FMT Remove this once we require compilers with proper C++20 support. 307// If the compiler has no concepts support, the format header will be disabled. 308// Without concepts support enable_if needs to be used and that too much effort 309// to support compilers with partial C++20 support. 310#if !defined(_LIBCPP_HAS_NO_CONCEPTS) 311 312// TODO FMT Move the implementation in this file to its own granular headers. 313 314// TODO FMT Evaluate which templates should be external templates. This 315// improves the efficiency of the header. However since the header is still 316// under heavy development and not all classes are stable it makes no sense 317// to do this optimization now. 318 319using format_args = basic_format_args<format_context>; 320#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 321using wformat_args = basic_format_args<wformat_context>; 322#endif 323 324template <class _Context, class... _Args> 325struct _LIBCPP_TEMPLATE_VIS __format_arg_store { 326 // TODO FMT Use a built-in array. 327 array<basic_format_arg<_Context>, sizeof...(_Args)> __args; 328}; 329 330template <class _Context = format_context, class... _Args> 331_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> 332make_format_args(const _Args&... __args) { 333 return {basic_format_arg<_Context>(__args)...}; 334} 335 336#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 337template <class... _Args> 338_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> 339make_wformat_args(const _Args&... __args) { 340 return _VSTD::make_format_args<wformat_context>(__args...); 341} 342#endif 343 344namespace __format { 345 346template <class _CharT, class _ParseCtx, class _Ctx> 347_LIBCPP_HIDE_FROM_ABI const _CharT* 348__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 349 _ParseCtx& __parse_ctx, _Ctx& __ctx) { 350 __format::__parse_number_result __r = 351 __format::__parse_arg_id(__begin, __end, __parse_ctx); 352 353 switch (*__r.__ptr) { 354 case _CharT(':'): 355 // The arg-id has a format-specifier, advance the input to the format-spec. 356 __parse_ctx.advance_to(__r.__ptr + 1); 357 break; 358 case _CharT('}'): 359 // The arg-id has no format-specifier. 360 __parse_ctx.advance_to(__r.__ptr); 361 break; 362 default: 363 __throw_format_error( 364 "The replacement field arg-id should terminate at a ':' or '}'"); 365 } 366 367 _VSTD::visit_format_arg( 368 [&](auto __arg) { 369 if constexpr (same_as<decltype(__arg), monostate>) 370 __throw_format_error("Argument index out of bounds"); 371 else { 372 formatter<decltype(__arg), _CharT> __formatter; 373 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 374 __ctx.advance_to(__formatter.format(__arg, __ctx)); 375 } 376 }, 377 __ctx.arg(__r.__value)); 378 379 __begin = __parse_ctx.begin(); 380 if (__begin == __end || *__begin != _CharT('}')) 381 __throw_format_error("The replacement field misses a terminating '}'"); 382 383 return ++__begin; 384} 385 386template <class _ParseCtx, class _Ctx> 387_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator 388__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 389 using _CharT = typename _ParseCtx::char_type; 390 static_assert(same_as<typename _Ctx::char_type, _CharT>); 391 392 const _CharT* __begin = __parse_ctx.begin(); 393 const _CharT* __end = __parse_ctx.end(); 394 typename _Ctx::iterator __out_it = __ctx.out(); 395 while (__begin != __end) { 396 switch (*__begin) { 397 case _CharT('{'): 398 ++__begin; 399 if (__begin == __end) 400 __throw_format_error("The format string terminates at a '{'"); 401 402 if (*__begin != _CharT('{')) [[likely]] { 403 __ctx.advance_to(_VSTD::move(__out_it)); 404 __begin = 405 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 406 __out_it = __ctx.out(); 407 408 // The output is written and __begin points to the next character. So 409 // start the next iteration. 410 continue; 411 } 412 // The string is an escape character. 413 break; 414 415 case _CharT('}'): 416 ++__begin; 417 if (__begin == __end || *__begin != _CharT('}')) 418 __throw_format_error( 419 "The format string contains an invalid escape sequence"); 420 421 break; 422 } 423 424 // Copy the character to the output verbatim. 425 *__out_it++ = *__begin++; 426 } 427 return __out_it; 428} 429 430} // namespace __format 431 432template <class _OutIt, class _CharT, class _FormatOutIt> 433requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 434 __vformat_to( 435 _OutIt __out_it, basic_string_view<_CharT> __fmt, 436 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 437 if constexpr (same_as<_OutIt, _FormatOutIt>) 438 return _VSTD::__format::__vformat_to( 439 basic_format_parse_context{__fmt, __args.__size()}, 440 _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 441 else { 442 basic_string<_CharT> __str; 443 _VSTD::__format::__vformat_to( 444 basic_format_parse_context{__fmt, __args.__size()}, 445 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args)); 446 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it)); 447 } 448} 449 450template <output_iterator<const char&> _OutIt> 451_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 452vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 453 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 454} 455 456#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 457template <output_iterator<const wchar_t&> _OutIt> 458_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 459vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 460 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 461} 462#endif 463 464template <output_iterator<const char&> _OutIt, class... _Args> 465_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 466format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) { 467 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 468 _VSTD::make_format_args(__args...)); 469} 470 471#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 472template <output_iterator<const wchar_t&> _OutIt, class... _Args> 473_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 474format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) { 475 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 476 _VSTD::make_wformat_args(__args...)); 477} 478#endif 479 480_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 481vformat(string_view __fmt, format_args __args) { 482 string __res; 483 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 484 return __res; 485} 486 487#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 488_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 489vformat(wstring_view __fmt, wformat_args __args) { 490 wstring __res; 491 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 492 return __res; 493} 494#endif 495 496template <class... _Args> 497_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 498format(string_view __fmt, const _Args&... __args) { 499 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 500} 501 502#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 503template <class... _Args> 504_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 505format(wstring_view __fmt, const _Args&... __args) { 506 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 507} 508#endif 509 510template <output_iterator<const char&> _OutIt, class... _Args> 511_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 512format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, 513 const _Args&... __args) { 514 // TODO FMT Improve PoC: using std::string is inefficient. 515 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 516 iter_difference_t<_OutIt> __s = __str.size(); 517 iter_difference_t<_OutIt> __m = 518 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 519 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 520 return {_VSTD::move(__out_it), __s}; 521} 522 523#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 524template <output_iterator<const wchar_t&> _OutIt, class... _Args> 525_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 526format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, 527 const _Args&... __args) { 528 // TODO FMT Improve PoC: using std::string is inefficient. 529 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 530 iter_difference_t<_OutIt> __s = __str.size(); 531 iter_difference_t<_OutIt> __m = 532 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 533 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 534 return {_VSTD::move(__out_it), __s}; 535} 536#endif 537 538template <class... _Args> 539_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 540formatted_size(string_view __fmt, const _Args&... __args) { 541 // TODO FMT Improve PoC: using std::string is inefficient. 542 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size(); 543} 544 545#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 546template <class... _Args> 547_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 548formatted_size(wstring_view __fmt, const _Args&... __args) { 549 // TODO FMT Improve PoC: using std::string is inefficient. 550 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size(); 551} 552#endif 553 554#ifndef _LIBCPP_HAS_NO_LOCALIZATION 555 556template <class _OutIt, class _CharT, class _FormatOutIt> 557requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 558 __vformat_to( 559 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 560 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 561 if constexpr (same_as<_OutIt, _FormatOutIt>) 562 return _VSTD::__format::__vformat_to( 563 basic_format_parse_context{__fmt, __args.__size()}, 564 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 565 _VSTD::move(__loc))); 566 else { 567 basic_string<_CharT> __str; 568 _VSTD::__format::__vformat_to( 569 basic_format_parse_context{__fmt, __args.__size()}, 570 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args, 571 _VSTD::move(__loc))); 572 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it)); 573 } 574} 575 576template <output_iterator<const char&> _OutIt> 577_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 578 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 579 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 580 __args); 581} 582 583#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 584template <output_iterator<const wchar_t&> _OutIt> 585_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 586 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 587 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 588 __args); 589} 590#endif 591 592template <output_iterator<const char&> _OutIt, class... _Args> 593_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 594 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) { 595 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 596 _VSTD::make_format_args(__args...)); 597} 598 599#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 600template <output_iterator<const wchar_t&> _OutIt, class... _Args> 601_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 602 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) { 603 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 604 _VSTD::make_wformat_args(__args...)); 605} 606#endif 607 608_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 609vformat(locale __loc, string_view __fmt, format_args __args) { 610 string __res; 611 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 612 __args); 613 return __res; 614} 615 616#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 617_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 618vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 619 wstring __res; 620 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 621 __args); 622 return __res; 623} 624#endif 625 626template <class... _Args> 627_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 628format(locale __loc, string_view __fmt, const _Args&... __args) { 629 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 630 _VSTD::make_format_args(__args...)); 631} 632 633#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 634template <class... _Args> 635_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 636format(locale __loc, wstring_view __fmt, const _Args&... __args) { 637 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 638 _VSTD::make_wformat_args(__args...)); 639} 640#endif 641 642template <output_iterator<const char&> _OutIt, class... _Args> 643_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 644format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 645 string_view __fmt, const _Args&... __args) { 646 // TODO FMT Improve PoC: using std::string is inefficient. 647 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 648 _VSTD::make_format_args(__args...)); 649 iter_difference_t<_OutIt> __s = __str.size(); 650 iter_difference_t<_OutIt> __m = 651 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 652 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 653 return {_VSTD::move(__out_it), __s}; 654} 655 656#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 657template <output_iterator<const wchar_t&> _OutIt, class... _Args> 658_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 659format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 660 wstring_view __fmt, const _Args&... __args) { 661 // TODO FMT Improve PoC: using std::string is inefficient. 662 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 663 _VSTD::make_wformat_args(__args...)); 664 iter_difference_t<_OutIt> __s = __str.size(); 665 iter_difference_t<_OutIt> __m = 666 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 667 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 668 return {_VSTD::move(__out_it), __s}; 669} 670#endif 671 672template <class... _Args> 673_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 674formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { 675 // TODO FMT Improve PoC: using std::string is inefficient. 676 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 677 _VSTD::make_format_args(__args...)) 678 .size(); 679} 680 681#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 682template <class... _Args> 683_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 684formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { 685 // TODO FMT Improve PoC: using std::string is inefficient. 686 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 687 _VSTD::make_wformat_args(__args...)) 688 .size(); 689} 690#endif 691 692#endif // _LIBCPP_HAS_NO_LOCALIZATION 693 694#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 695#endif //_LIBCPP_STD_VER > 17 696 697_LIBCPP_END_NAMESPACE_STD 698 699_LIBCPP_POP_MACROS 700 701#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 702 703#endif // _LIBCPP_FORMAT 704