1// -*- C++ -*- 2//===--------------------------- format -----------------------------------===// 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/formatter.h> 282#include <__format/formatter_bool.h> 283#include <__format/formatter_char.h> 284#include <__format/formatter_integer.h> 285#include <__format/formatter_string.h> 286#include <__format/parser_std_format_spec.h> 287#include <__variant/monostate.h> 288#include <array> 289#include <concepts> 290#include <string> 291#include <string_view> 292#include <type_traits> 293 294#ifndef _LIBCPP_HAS_NO_LOCALIZATION 295#include <locale> 296#endif 297 298#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 299#pragma GCC system_header 300#endif 301 302_LIBCPP_PUSH_MACROS 303#include <__undef_macros> 304 305_LIBCPP_BEGIN_NAMESPACE_STD 306 307#if _LIBCPP_STD_VER > 17 308 309// TODO FMT Remove this once we require compilers with proper C++20 support. 310// If the compiler has no concepts support, the format header will be disabled. 311// Without concepts support enable_if needs to be used and that too much effort 312// to support compilers with partial C++20 support. 313#if !defined(_LIBCPP_HAS_NO_CONCEPTS) 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 _OutIt, class _CharT> 326using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>; 327 328template <class _Context, class... _Args> 329struct _LIBCPP_TEMPLATE_VIS __format_arg_store { 330 // TODO FMT Use a built-in array. 331 array<basic_format_arg<_Context>, sizeof...(_Args)> __args; 332}; 333 334template <class _Context = format_context, class... _Args> 335_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> 336make_format_args(const _Args&... __args) { 337 return {basic_format_arg<_Context>(__args)...}; 338} 339 340#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 341template <class... _Args> 342_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> 343make_wformat_args(const _Args&... __args) { 344 return _VSTD::make_format_args<wformat_context>(__args...); 345} 346#endif 347 348namespace __format { 349 350template <class _Tp, class _CharT> 351requires(is_arithmetic_v<_Tp> && 352 !same_as<_Tp, bool>) struct _LIBCPP_HIDE_FROM_ABI 353 __formatter_arithmetic { 354 _LIBCPP_HIDE_FROM_ABI 355 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 356 // TODO FMT Implement 357 return __parse_ctx.begin(); 358 } 359 360 _LIBCPP_HIDE_FROM_ABI 361 auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) { 362 return __handle_format(__value, __ctx); 363 } 364 365private: 366 template <class _Uv> 367 _LIBCPP_HIDDEN static string 368 __convert(_Uv __value) requires(same_as<_CharT, char>) { 369 return _VSTD::to_string(__value); 370 } 371#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 372 template <class _Uv> 373 _LIBCPP_HIDDEN static wstring 374 __convert(_Uv __value) requires(same_as<_CharT, wchar_t>) { 375 return _VSTD::to_wstring(__value); 376 } 377#endif 378 379 template <class _Uv> 380 _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx) 381 -> decltype(__ctx.out()) 382 { 383 // TODO FMT Implement using formatting arguments 384 // TODO FMT Improve PoC since using std::to_string is inefficient. 385 // Note the code doesn't use std::string::iterator since the unit tests 386 // test with debug iterators and they fail with strings created from 387 // std::to_string. 388 auto __str = __convert(__value); 389 auto __out_it = __ctx.out(); 390 for (size_t __i = 0, __e = __str.size(); __i != __e; ++__i) 391 *__out_it++ = __str[__i]; 392 return __out_it; 393 } 394}; 395} // namespace __format 396 397// These specializations are helper stubs and not proper formatters. 398// TODO FMT Implement the proper formatter specializations. 399 400// Floating point types. 401// TODO FMT There are no replacements for the floating point stubs due to not 402// having floating point support in std::to_chars yet. These stubs aren't 403// removed since they are useful for developing the real versions. 404// Ultimately the stubs should be implemented properly and this code can be 405// removed. 406#if 0 407template <class _CharT> 408struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT> 409 : public __format::__formatter_arithmetic<float, _CharT> {}; 410template <class _CharT> 411struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 412 formatter<double, _CharT> 413 : public __format::__formatter_arithmetic<double, _CharT> {}; 414template <class _CharT> 415struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 416 formatter<long double, _CharT> 417 : public __format::__formatter_arithmetic<long double, _CharT> {}; 418#endif 419 420namespace __format { 421 422template <class _CharT, class _ParseCtx, class _Ctx> 423_LIBCPP_HIDE_FROM_ABI const _CharT* 424__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 425 _ParseCtx& __parse_ctx, _Ctx& __ctx) { 426 __format::__parse_number_result __r = 427 __format::__parse_arg_id(__begin, __end, __parse_ctx); 428 429 switch (*__r.__ptr) { 430 case _CharT(':'): 431 // The arg-id has a format-specifier, advance the input to the format-spec. 432 __parse_ctx.advance_to(__r.__ptr + 1); 433 break; 434 case _CharT('}'): 435 // The arg-id has no format-specifier. 436 __parse_ctx.advance_to(__r.__ptr); 437 break; 438 default: 439 __throw_format_error( 440 "The replacement field arg-id should terminate at a ':' or '}'"); 441 } 442 443 _VSTD::visit_format_arg( 444 [&](auto __arg) { 445 if constexpr (same_as<decltype(__arg), monostate>) 446 __throw_format_error("Argument index out of bounds"); 447 else { 448 formatter<decltype(__arg), _CharT> __formatter; 449 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 450 __ctx.advance_to(__formatter.format(__arg, __ctx)); 451 } 452 }, 453 __ctx.arg(__r.__value)); 454 455 __begin = __parse_ctx.begin(); 456 if (__begin == __end || *__begin != _CharT('}')) 457 __throw_format_error("The replacement field misses a terminating '}'"); 458 459 return ++__begin; 460} 461 462template <class _ParseCtx, class _Ctx> 463_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator 464__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 465 using _CharT = typename _ParseCtx::char_type; 466 static_assert(same_as<typename _Ctx::char_type, _CharT>); 467 468 const _CharT* __begin = __parse_ctx.begin(); 469 const _CharT* __end = __parse_ctx.end(); 470 typename _Ctx::iterator __out_it = __ctx.out(); 471 while (__begin != __end) { 472 switch (*__begin) { 473 case _CharT('{'): 474 ++__begin; 475 if (__begin == __end) 476 __throw_format_error("The format string terminates at a '{'"); 477 478 if (*__begin != _CharT('{')) [[likely]] { 479 __ctx.advance_to(_VSTD::move(__out_it)); 480 __begin = 481 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 482 __out_it = __ctx.out(); 483 484 // The output is written and __begin points to the next character. So 485 // start the next iteration. 486 continue; 487 } 488 // The string is an escape character. 489 break; 490 491 case _CharT('}'): 492 ++__begin; 493 if (__begin == __end || *__begin != _CharT('}')) 494 __throw_format_error( 495 "The format string contains an invalid escape sequence"); 496 497 break; 498 } 499 500 // Copy the character to the output verbatim. 501 *__out_it++ = *__begin++; 502 } 503 return __out_it; 504} 505 506} // namespace __format 507 508template <class _OutIt, class _CharT> 509requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 510 __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt, 511 format_args_t<type_identity_t<_OutIt>, _CharT> __args) { 512 return __format::__vformat_to( 513 basic_format_parse_context{__fmt, __args.__size()}, 514 _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 515} 516 517template <output_iterator<const char&> _OutIt> 518_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 519vformat_to(_OutIt __out_it, string_view __fmt, 520 format_args_t<type_identity_t<_OutIt>, char> __args) { 521 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 522} 523 524#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 525template <output_iterator<const wchar_t&> _OutIt> 526_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 527vformat_to(_OutIt __out_it, wstring_view __fmt, 528 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) { 529 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 530} 531#endif 532 533template <output_iterator<const char&> _OutIt, class... _Args> 534_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 535format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) { 536 return _VSTD::vformat_to( 537 _VSTD::move(__out_it), __fmt, 538 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...)); 539} 540 541#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 542template <output_iterator<const wchar_t&> _OutIt, class... _Args> 543_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 544format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) { 545 return _VSTD::vformat_to( 546 _VSTD::move(__out_it), __fmt, 547 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>( 548 __args...)); 549} 550#endif 551 552inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 553vformat(string_view __fmt, format_args __args) { 554 string __res; 555 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 556 return __res; 557} 558 559#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 560inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 561vformat(wstring_view __fmt, wformat_args __args) { 562 wstring __res; 563 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 564 return __res; 565} 566#endif 567 568template <class... _Args> 569_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 570format(string_view __fmt, const _Args&... __args) { 571 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 572} 573 574#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 575template <class... _Args> 576_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 577format(wstring_view __fmt, const _Args&... __args) { 578 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 579} 580#endif 581 582template <class _OutIt> 583struct _LIBCPP_TEMPLATE_VIS format_to_n_result { 584 _OutIt out; 585 iter_difference_t<_OutIt> size; 586}; 587 588template <output_iterator<const char&> _OutIt, class... _Args> 589_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 590format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, 591 const _Args&... __args) { 592 // TODO FMT Improve PoC: using std::string is inefficient. 593 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 594 iter_difference_t<_OutIt> __s = __str.size(); 595 iter_difference_t<_OutIt> __m = 596 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 597 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 598 return {_VSTD::move(__out_it), __s}; 599} 600 601#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 602template <output_iterator<const wchar_t&> _OutIt, class... _Args> 603_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 604format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, 605 const _Args&... __args) { 606 // TODO FMT Improve PoC: using std::string is inefficient. 607 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 608 iter_difference_t<_OutIt> __s = __str.size(); 609 iter_difference_t<_OutIt> __m = 610 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 611 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 612 return {_VSTD::move(__out_it), __s}; 613} 614#endif 615 616template <class... _Args> 617_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 618formatted_size(string_view __fmt, const _Args&... __args) { 619 // TODO FMT Improve PoC: using std::string is inefficient. 620 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size(); 621} 622 623#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 624template <class... _Args> 625_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 626formatted_size(wstring_view __fmt, const _Args&... __args) { 627 // TODO FMT Improve PoC: using std::string is inefficient. 628 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size(); 629} 630#endif 631 632#ifndef _LIBCPP_HAS_NO_LOCALIZATION 633 634template <class _OutIt, class _CharT> 635requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 636 __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 637 format_args_t<type_identity_t<_OutIt>, _CharT> __args) { 638 return __format::__vformat_to( 639 basic_format_parse_context{__fmt, __args.__size()}, 640 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 641 _VSTD::move(__loc))); 642} 643 644template <output_iterator<const char&> _OutIt> 645_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 646vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, 647 format_args_t<type_identity_t<_OutIt>, char> __args) { 648 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 649 __args); 650} 651 652#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 653template <output_iterator<const wchar_t&> _OutIt> 654_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 655vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, 656 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) { 657 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 658 __args); 659} 660#endif 661 662template <output_iterator<const char&> _OutIt, class... _Args> 663_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 664 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) { 665 return _VSTD::vformat_to( 666 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 667 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...)); 668} 669 670#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 671template <output_iterator<const wchar_t&> _OutIt, class... _Args> 672_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 673 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) { 674 return _VSTD::vformat_to( 675 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 676 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>( 677 __args...)); 678} 679#endif 680 681inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 682vformat(locale __loc, string_view __fmt, format_args __args) { 683 string __res; 684 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 685 __args); 686 return __res; 687} 688 689#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 690inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 691vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 692 wstring __res; 693 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 694 __args); 695 return __res; 696} 697#endif 698 699template <class... _Args> 700_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 701format(locale __loc, string_view __fmt, const _Args&... __args) { 702 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 703 _VSTD::make_format_args(__args...)); 704} 705 706#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 707template <class... _Args> 708_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 709format(locale __loc, wstring_view __fmt, const _Args&... __args) { 710 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 711 _VSTD::make_wformat_args(__args...)); 712} 713#endif 714 715template <output_iterator<const char&> _OutIt, class... _Args> 716_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 717format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 718 string_view __fmt, const _Args&... __args) { 719 // TODO FMT Improve PoC: using std::string is inefficient. 720 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 721 _VSTD::make_format_args(__args...)); 722 iter_difference_t<_OutIt> __s = __str.size(); 723 iter_difference_t<_OutIt> __m = 724 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 725 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 726 return {_VSTD::move(__out_it), __s}; 727} 728 729#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 730template <output_iterator<const wchar_t&> _OutIt, class... _Args> 731_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 732format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 733 wstring_view __fmt, const _Args&... __args) { 734 // TODO FMT Improve PoC: using std::string is inefficient. 735 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 736 _VSTD::make_wformat_args(__args...)); 737 iter_difference_t<_OutIt> __s = __str.size(); 738 iter_difference_t<_OutIt> __m = 739 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 740 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 741 return {_VSTD::move(__out_it), __s}; 742} 743#endif 744 745template <class... _Args> 746_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 747formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { 748 // TODO FMT Improve PoC: using std::string is inefficient. 749 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 750 _VSTD::make_format_args(__args...)) 751 .size(); 752} 753 754#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 755template <class... _Args> 756_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 757formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { 758 // TODO FMT Improve PoC: using std::string is inefficient. 759 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 760 _VSTD::make_wformat_args(__args...)) 761 .size(); 762} 763#endif 764 765#endif // _LIBCPP_HAS_NO_LOCALIZATION 766 767#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 768#endif //_LIBCPP_STD_VER > 17 769 770_LIBCPP_END_NAMESPACE_STD 771 772_LIBCPP_POP_MACROS 773 774#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 775 776#endif // _LIBCPP_FORMAT 777