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_parse_context.h> 279#include <__format/format_string.h> 280#include <__format/formatter.h> 281#include <__variant/monostate.h> 282#include <array> 283#include <concepts> 284#include <string> 285#include <string_view> 286#include <type_traits> 287 288#ifndef _LIBCPP_HAS_NO_LOCALIZATION 289#include <locale> 290#endif 291 292#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 293#pragma GCC system_header 294#endif 295 296_LIBCPP_PUSH_MACROS 297#include <__undef_macros> 298 299_LIBCPP_BEGIN_NAMESPACE_STD 300 301#if _LIBCPP_STD_VER > 17 302 303// TODO FMT Remove this once we require compilers with proper C++20 support. 304// If the compiler has no concepts support, the format header will be disabled. 305// Without concepts support enable_if needs to be used and that too much effort 306// to support compilers with partial C++20 support. 307#if !defined(_LIBCPP_HAS_NO_CONCEPTS) 308 309// TODO FMT Evaluate which templates should be external templates. This 310// improves the efficiency of the header. However since the header is still 311// under heavy development and not all classes are stable it makes no sense 312// to do this optimization now. 313 314using format_args = basic_format_args<format_context>; 315using wformat_args = basic_format_args<wformat_context>; 316 317template <class _OutIt, class _CharT> 318using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>; 319 320template <class _Context, class... _Args> 321struct _LIBCPP_TEMPLATE_VIS __format_arg_store { 322 // TODO FMT Use a built-in array. 323 array<basic_format_arg<_Context>, sizeof...(_Args)> __args; 324}; 325 326template <class _Context = format_context, class... _Args> 327_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> 328make_format_args(const _Args&... __args) { 329 return {basic_format_arg<_Context>(__args)...}; 330} 331 332template <class... _Args> 333_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> 334make_wformat_args(const _Args&... __args) { 335 return _VSTD::make_format_args<wformat_context>(__args...); 336} 337 338namespace __format { 339template <class _Tp, class _CharT> 340struct _LIBCPP_TEMPLATE_VIS __formatter_char { 341 _LIBCPP_HIDE_FROM_ABI 342 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 343 // TODO FMT Implement this function. 344 return __parse_ctx.begin(); 345 } 346 347 _LIBCPP_HIDE_FROM_ABI 348 auto format(_Tp __c, auto& __ctx) -> decltype(__ctx.out()) { 349 // TODO FMT Implement the parsed formatting arguments. 350 auto __out_it = __ctx.out(); 351 *__out_it++ = _CharT(__c); 352 return __out_it; 353 } 354}; 355 356template <class _CharT> 357struct _LIBCPP_TEMPLATE_VIS __formatter_c_string { 358 _LIBCPP_HIDE_FROM_ABI 359 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 360 // TODO FMT Implement this function. 361 return __parse_ctx.begin(); 362 } 363 364 _LIBCPP_HIDE_FROM_ABI 365 auto format(const _CharT* __str, auto& __ctx) -> decltype(__ctx.out()) { 366 // TODO FMT Implement the parsed formatting arguments. 367 auto __out_it = __ctx.out(); 368 while (*__str) 369 *__out_it++ = *__str++; 370 return __out_it; 371 } 372}; 373 374template <class _CharT> 375struct _LIBCPP_TEMPLATE_VIS __formatter_string { 376 _LIBCPP_HIDE_FROM_ABI 377 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 378 // TODO FMT Implement this function. 379 return __parse_ctx.begin(); 380 } 381 382 _LIBCPP_HIDE_FROM_ABI 383 auto format(basic_string_view<_CharT> __str, auto& __ctx) 384 -> decltype(__ctx.out()) { 385 // TODO FMT Implement the parsed formatting arguments. 386 auto __out_it = __ctx.out(); 387 for (const auto __c : __str) 388 *__out_it++ = __c; 389 return __out_it; 390 } 391}; 392 393template <class _Tp, class _CharT> 394requires(is_arithmetic_v<_Tp> && 395 !same_as<_Tp, bool>) struct _LIBCPP_HIDE_FROM_ABI 396 __formatter_arithmetic { 397 _LIBCPP_HIDE_FROM_ABI 398 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 399 // TODO FMT Implement 400 return __parse_ctx.begin(); 401 } 402 403 _LIBCPP_HIDE_FROM_ABI 404 auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) { 405 return __handle_format(__value, __ctx); 406 } 407 408private: 409 template <class _Uv> 410 _LIBCPP_HIDDEN static string 411 __convert(_Uv __value) requires(same_as<_CharT, char>) { 412 return _VSTD::to_string(__value); 413 } 414 template <class _Uv> 415 _LIBCPP_HIDDEN static wstring 416 __convert(_Uv __value) requires(same_as<_CharT, wchar_t>) { 417 return _VSTD::to_wstring(__value); 418 } 419 420 template <class _Uv> 421 _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx) 422 -> decltype(__ctx.out()) 423#ifndef _LIBCPP_HAS_NO_INT128 424 requires(!same_as<_Uv, __int128_t> && !same_as<_Uv, __uint128_t>) 425#endif 426 { 427 // TODO FMT Implement using formatting arguments 428 // TODO FMT Improve PoC since using std::to_string is inefficient. 429 // Note the code doesn't use std::string::iterator since the unit tests 430 // test with debug iterators and they fail with strings created from 431 // std::to_string. 432 auto __str = __convert(__value); 433 auto __out_it = __ctx.out(); 434 for (size_t __i = 0, __e = __str.size(); __i != __e; ++__i) 435 *__out_it++ = __str[__i]; 436 return __out_it; 437 } 438#ifndef _LIBCPP_HAS_NO_INT128 439 template <class _Uv> 440 _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx) 441 -> decltype(__ctx.out()) requires(same_as<_Uv, __int128_t> || 442 same_as<_Uv, __uint128_t>) { 443 using _To = conditional_t<is_signed_v<_Uv>, long long, unsigned long long>; 444 // TODO FMT Implement full 128-bit support. 445 if (__value < numeric_limits<_To>::min() || 446 __value > numeric_limits<_To>::max()) 447 __throw_format_error("128-bit value is outside of implemented range"); 448 449 return __handle_format(static_cast<_To>(__value), __ctx); 450 } 451#endif 452}; 453} // namespace __format 454 455// These specializations are helper stubs and not proper formatters. 456// TODO FMT Implement the proper formatter specializations. 457 458// [format.formatter.spec]/2.1 The specializations 459 460template <> 461struct _LIBCPP_TEMPLATE_VIS formatter<char, char> 462 : public __format::__formatter_char<char, char> {}; 463 464template <> 465struct _LIBCPP_TEMPLATE_VIS formatter<char, wchar_t> 466 : public __format::__formatter_char<char, wchar_t> {}; 467 468template <> 469struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t> 470 : public __format::__formatter_char<wchar_t, wchar_t> {}; 471 472// [format.formatter.spec]/2.2 For each charT, the string type specializations 473 474template <class _CharT> 475struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> 476 : public __format::__formatter_c_string<_CharT> { 477 using _Base = __format::__formatter_c_string<_CharT>; 478 479 _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx) 480 -> decltype(__ctx.out()) { 481 _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have " 482 "prevented an invalid pointer"); 483 return _Base::format(__str, __ctx); 484 } 485}; 486 487template <class _CharT> 488struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT*, _CharT> 489 : public __format::__formatter_c_string<_CharT> {}; 490 491template <class _CharT, size_t _Size> 492struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT[_Size], _CharT> 493 : public __format::__formatter_string<_CharT> { 494 using _Base = __format::__formatter_string<_CharT>; 495 496 _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx) 497 -> decltype(__ctx.out()) { 498 return _Base::format(_VSTD::basic_string_view<_CharT>(__str, _Size), __ctx); 499 } 500}; 501 502template <class _CharT, class _Traits, class _Allocator> 503struct _LIBCPP_TEMPLATE_VIS 504 formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT> 505 : public __format::__formatter_string<_CharT> { 506 using _Base = __format::__formatter_string<_CharT>; 507 508 _LIBCPP_HIDE_FROM_ABI auto 509 format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx) 510 -> decltype(__ctx.out()) { 511 return _Base::format(_VSTD::basic_string_view<_CharT>(__str), __ctx); 512 } 513}; 514 515template <class _CharT, class _Traits> 516struct _LIBCPP_TEMPLATE_VIS 517 formatter<basic_string_view<_CharT, _Traits>, _CharT> 518 : public __format::__formatter_string<_CharT> {}; 519 520// [format.formatter.spec]/2.3 521// For each charT, for each cv-unqualified arithmetic type ArithmeticT other 522// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization 523 524// Boolean. 525template <class _CharT> 526struct _LIBCPP_TEMPLATE_VIS formatter<bool, _CharT> { 527 _LIBCPP_HIDE_FROM_ABI 528 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 529 // TODO FMT Implement 530 return __parse_ctx.begin(); 531 } 532 533 _LIBCPP_HIDE_FROM_ABI 534 auto format(bool __b, auto& __ctx) -> decltype(__ctx.out()) { 535 // TODO FMT Implement using formatting arguments 536 auto __out_it = __ctx.out(); 537 *__out_it++ = _CharT('0') + __b; 538 return __out_it; 539 } 540}; 541 542// Signed integral types. 543template <class _CharT> 544struct _LIBCPP_TEMPLATE_VIS formatter<signed char, _CharT> 545 : public __format::__formatter_arithmetic<signed char, _CharT> {}; 546template <class _CharT> 547struct _LIBCPP_TEMPLATE_VIS formatter<short, _CharT> 548 : public __format::__formatter_arithmetic<short, _CharT> {}; 549template <class _CharT> 550struct _LIBCPP_TEMPLATE_VIS formatter<int, _CharT> 551 : public __format::__formatter_arithmetic<int, _CharT> {}; 552template <class _CharT> 553struct _LIBCPP_TEMPLATE_VIS formatter<long, _CharT> 554 : public __format::__formatter_arithmetic<long, _CharT> {}; 555template <class _CharT> 556struct _LIBCPP_TEMPLATE_VIS formatter<long long, _CharT> 557 : public __format::__formatter_arithmetic<long long, _CharT> {}; 558#ifndef _LIBCPP_HAS_NO_INT128 559template <class _CharT> 560struct _LIBCPP_TEMPLATE_VIS formatter<__int128_t, _CharT> 561 : public __format::__formatter_arithmetic<__int128_t, _CharT> {}; 562#endif 563 564// Unsigned integral types. 565template <class _CharT> 566struct _LIBCPP_TEMPLATE_VIS formatter<unsigned char, _CharT> 567 : public __format::__formatter_arithmetic<unsigned char, _CharT> {}; 568template <class _CharT> 569struct _LIBCPP_TEMPLATE_VIS formatter<unsigned short, _CharT> 570 : public __format::__formatter_arithmetic<unsigned short, _CharT> {}; 571template <class _CharT> 572struct _LIBCPP_TEMPLATE_VIS formatter<unsigned, _CharT> 573 : public __format::__formatter_arithmetic<unsigned, _CharT> {}; 574template <class _CharT> 575struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long, _CharT> 576 : public __format::__formatter_arithmetic<unsigned long, _CharT> {}; 577template <class _CharT> 578struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long long, _CharT> 579 : public __format::__formatter_arithmetic<unsigned long long, _CharT> {}; 580#ifndef _LIBCPP_HAS_NO_INT128 581template <class _CharT> 582struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT> 583 : public __format::__formatter_arithmetic<__uint128_t, _CharT> {}; 584#endif 585 586// Floating point types. 587// TODO FMT There are no replacements for the floating point stubs due to not 588// having floating point support in std::to_chars yet. These stubs aren't 589// removed since they are useful for developing the real versions. 590// Ultimately the stubs should be implemented properly and this code can be 591// removed. 592#if 0 593template <class _CharT> 594struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT> 595 : public __format::__formatter_arithmetic<float, _CharT> {}; 596template <class _CharT> 597struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 598 formatter<double, _CharT> 599 : public __format::__formatter_arithmetic<double, _CharT> {}; 600template <class _CharT> 601struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 602 formatter<long double, _CharT> 603 : public __format::__formatter_arithmetic<long double, _CharT> {}; 604#endif 605 606namespace __format { 607 608template <class _CharT, class _ParseCtx, class _Ctx> 609_LIBCPP_HIDE_FROM_ABI const _CharT* 610__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 611 _ParseCtx& __parse_ctx, _Ctx& __ctx) { 612 __format::__parse_number_result __r = 613 __format::__parse_arg_id(__begin, __end, __parse_ctx); 614 615 switch (*__r.__ptr) { 616 case _CharT(':'): 617 // The arg-id has a format-specifier, advance the input to the format-spec. 618 __parse_ctx.advance_to(__r.__ptr + 1); 619 break; 620 case _CharT('}'): 621 // The arg-id has no format-specifier. 622 __parse_ctx.advance_to(__r.__ptr); 623 break; 624 default: 625 __throw_format_error( 626 "The replacement field arg-id should terminate at a ':' or '}'"); 627 } 628 629 _VSTD::visit_format_arg( 630 [&](auto __arg) { 631 if constexpr (same_as<decltype(__arg), monostate>) 632 __throw_format_error("Argument index out of bounds"); 633 else { 634 formatter<decltype(__arg), _CharT> __formatter; 635 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 636 __ctx.advance_to(__formatter.format(__arg, __ctx)); 637 } 638 }, 639 __ctx.arg(__r.__value)); 640 641 __begin = __parse_ctx.begin(); 642 if (__begin == __end || *__begin != _CharT('}')) 643 __throw_format_error("The replacement field misses a terminating '}'"); 644 645 return ++__begin; 646} 647 648template <class _ParseCtx, class _Ctx> 649_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator 650__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 651 using _CharT = typename _ParseCtx::char_type; 652 static_assert(same_as<typename _Ctx::char_type, _CharT>); 653 654 const _CharT* __begin = __parse_ctx.begin(); 655 const _CharT* __end = __parse_ctx.end(); 656 typename _Ctx::iterator __out_it = __ctx.out(); 657 while (__begin != __end) { 658 switch (*__begin) { 659 case _CharT('{'): 660 ++__begin; 661 if (__begin == __end) 662 __throw_format_error("The format string terminates at a '{'"); 663 664 if (*__begin != _CharT('{')) [[likely]] { 665 __ctx.advance_to(_VSTD::move(__out_it)); 666 __begin = 667 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 668 __out_it = __ctx.out(); 669 670 // The output is written and __begin points to the next character. So 671 // start the next iteration. 672 continue; 673 } 674 // The string is an escape character. 675 break; 676 677 case _CharT('}'): 678 ++__begin; 679 if (__begin == __end || *__begin != _CharT('}')) 680 __throw_format_error( 681 "The format string contains an invalid escape sequence"); 682 683 break; 684 } 685 686 // Copy the character to the output verbatim. 687 *__out_it++ = *__begin++; 688 } 689 return __out_it; 690} 691 692} // namespace __format 693 694template <class _OutIt, class _CharT> 695requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 696 __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt, 697 format_args_t<type_identity_t<_OutIt>, _CharT> __args) { 698 return __format::__vformat_to( 699 basic_format_parse_context{__fmt, __args.__size()}, 700 _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 701} 702 703template <output_iterator<const char&> _OutIt> 704_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 705vformat_to(_OutIt __out_it, string_view __fmt, 706 format_args_t<type_identity_t<_OutIt>, char> __args) { 707 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 708} 709 710template <output_iterator<const wchar_t&> _OutIt> 711_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 712vformat_to(_OutIt __out_it, wstring_view __fmt, 713 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) { 714 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 715} 716 717template <output_iterator<const char&> _OutIt, class... _Args> 718_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 719format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) { 720 return _VSTD::vformat_to( 721 _VSTD::move(__out_it), __fmt, 722 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...)); 723} 724 725template <output_iterator<const wchar_t&> _OutIt, class... _Args> 726_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 727format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) { 728 return _VSTD::vformat_to( 729 _VSTD::move(__out_it), __fmt, 730 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>( 731 __args...)); 732} 733 734inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 735vformat(string_view __fmt, format_args __args) { 736 string __res; 737 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 738 return __res; 739} 740 741inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 742vformat(wstring_view __fmt, wformat_args __args) { 743 wstring __res; 744 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 745 return __res; 746} 747 748template <class... _Args> 749_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 750format(string_view __fmt, const _Args&... __args) { 751 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 752} 753 754template <class... _Args> 755_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 756format(wstring_view __fmt, const _Args&... __args) { 757 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 758} 759 760template <class _OutIt> 761struct _LIBCPP_TEMPLATE_VIS format_to_n_result { 762 _OutIt out; 763 iter_difference_t<_OutIt> size; 764}; 765 766template <output_iterator<const char&> _OutIt, class... _Args> 767_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 768format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, 769 const _Args&... __args) { 770 // TODO FMT Improve PoC: using std::string is inefficient. 771 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 772 iter_difference_t<_OutIt> __s = __str.size(); 773 iter_difference_t<_OutIt> __m = 774 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 775 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 776 return {_VSTD::move(__out_it), __s}; 777} 778 779template <output_iterator<const wchar_t&> _OutIt, class... _Args> 780_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 781format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, 782 const _Args&... __args) { 783 // TODO FMT Improve PoC: using std::string is inefficient. 784 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 785 iter_difference_t<_OutIt> __s = __str.size(); 786 iter_difference_t<_OutIt> __m = 787 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 788 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 789 return {_VSTD::move(__out_it), __s}; 790} 791 792template <class... _Args> 793_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 794formatted_size(string_view __fmt, const _Args&... __args) { 795 // TODO FMT Improve PoC: using std::string is inefficient. 796 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size(); 797} 798 799template <class... _Args> 800_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 801formatted_size(wstring_view __fmt, const _Args&... __args) { 802 // TODO FMT Improve PoC: using std::string is inefficient. 803 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size(); 804} 805 806#ifndef _LIBCPP_HAS_NO_LOCALIZATION 807 808template <class _OutIt, class _CharT> 809requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 810 __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 811 format_args_t<type_identity_t<_OutIt>, _CharT> __args) { 812 return __format::__vformat_to( 813 basic_format_parse_context{__fmt, __args.__size()}, 814 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 815 _VSTD::move(__loc))); 816} 817 818template <output_iterator<const char&> _OutIt> 819_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 820vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, 821 format_args_t<type_identity_t<_OutIt>, char> __args) { 822 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 823 __args); 824} 825 826template <output_iterator<const wchar_t&> _OutIt> 827_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 828vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, 829 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) { 830 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 831 __args); 832} 833 834template <output_iterator<const char&> _OutIt, class... _Args> 835_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 836 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) { 837 return _VSTD::vformat_to( 838 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 839 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...)); 840} 841 842template <output_iterator<const wchar_t&> _OutIt, class... _Args> 843_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 844 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) { 845 return _VSTD::vformat_to( 846 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 847 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>( 848 __args...)); 849} 850 851inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 852vformat(locale __loc, string_view __fmt, format_args __args) { 853 string __res; 854 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 855 __args); 856 return __res; 857} 858 859inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 860vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 861 wstring __res; 862 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 863 __args); 864 return __res; 865} 866 867template <class... _Args> 868_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 869format(locale __loc, string_view __fmt, const _Args&... __args) { 870 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 871 _VSTD::make_format_args(__args...)); 872} 873 874template <class... _Args> 875_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 876format(locale __loc, wstring_view __fmt, const _Args&... __args) { 877 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 878 _VSTD::make_wformat_args(__args...)); 879} 880 881template <output_iterator<const char&> _OutIt, class... _Args> 882_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 883format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 884 string_view __fmt, const _Args&... __args) { 885 // TODO FMT Improve PoC: using std::string is inefficient. 886 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 887 _VSTD::make_format_args(__args...)); 888 iter_difference_t<_OutIt> __s = __str.size(); 889 iter_difference_t<_OutIt> __m = 890 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 891 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 892 return {_VSTD::move(__out_it), __s}; 893} 894 895template <output_iterator<const wchar_t&> _OutIt, class... _Args> 896_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 897format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 898 wstring_view __fmt, const _Args&... __args) { 899 // TODO FMT Improve PoC: using std::string is inefficient. 900 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 901 _VSTD::make_wformat_args(__args...)); 902 iter_difference_t<_OutIt> __s = __str.size(); 903 iter_difference_t<_OutIt> __m = 904 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 905 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 906 return {_VSTD::move(__out_it), __s}; 907} 908 909template <class... _Args> 910_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 911formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { 912 // TODO FMT Improve PoC: using std::string is inefficient. 913 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 914 _VSTD::make_format_args(__args...)) 915 .size(); 916} 917 918template <class... _Args> 919_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 920formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { 921 // TODO FMT Improve PoC: using std::string is inefficient. 922 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 923 _VSTD::make_wformat_args(__args...)) 924 .size(); 925} 926 927#endif // _LIBCPP_HAS_NO_LOCALIZATION 928 929#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 930#endif //_LIBCPP_STD_VER > 17 931 932_LIBCPP_END_NAMESPACE_STD 933 934_LIBCPP_POP_MACROS 935 936#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 937 938#endif // _LIBCPP_FORMAT 939