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