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