Home | History | Annotate | Line # | Download | only in std
      1 // <format> Formatting -*- C++ -*-
      2 
      3 // Copyright The GNU Toolchain Authors.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/format
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #ifndef _GLIBCXX_FORMAT
     30 #define _GLIBCXX_FORMAT 1
     31 
     32 #pragma GCC system_header
     33 
     34 #include <bits/requires_hosted.h> // for std::string
     35 
     36 #define __glibcxx_want_format
     37 #define __glibcxx_want_format_ranges
     38 #define __glibcxx_want_format_uchar
     39 #include <bits/version.h>
     40 
     41 #ifdef __cpp_lib_format // C++ >= 20 && HOSTED
     42 
     43 #include <array>
     44 #include <charconv>
     45 #include <concepts>
     46 #include <limits>
     47 #include <locale>
     48 #include <optional>
     49 #include <span>
     50 #include <string_view>
     51 #include <string>
     52 #include <variant>	       // monostate (TODO: move to bits/utility.h?)
     53 #include <bits/ranges_base.h>  // input_range, range_reference_t
     54 #include <bits/ranges_util.h>  // subrange
     55 #include <bits/ranges_algobase.h> // ranges::copy
     56 #include <bits/stl_iterator.h> // back_insert_iterator
     57 #include <bits/stl_pair.h>     // __is_pair
     58 #include <bits/unicode.h>      // __is_scalar_value, _Utf_view, etc.
     59 #include <bits/utility.h>      // tuple_size_v
     60 #include <ext/numeric_traits.h> // __int_traits
     61 
     62 #if !__has_builtin(__builtin_toupper)
     63 # include <cctype>
     64 #endif
     65 
     66 namespace std _GLIBCXX_VISIBILITY(default)
     67 {
     68 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     69 
     70   // [format.context], class template basic_format_context
     71   template<typename _Out, typename _CharT> class basic_format_context;
     72 
     73   // [format.fmt.string], class template basic_format_string
     74   template<typename _CharT, typename... _Args> struct basic_format_string;
     75 
     76 /// @cond undocumented
     77 namespace __format
     78 {
     79   // Type-erased character sink.
     80   template<typename _CharT> class _Sink;
     81   // Output iterator that writes to a type-erase character sink.
     82   template<typename _CharT>
     83     class _Sink_iter;
     84 
     85   template<typename _CharT>
     86     using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>;
     87 
     88   template<typename _CharT>
     89     struct _Runtime_format_string
     90     {
     91       [[__gnu__::__always_inline__]]
     92       _Runtime_format_string(basic_string_view<_CharT> __s) noexcept
     93       : _M_str(__s) { }
     94 
     95       _Runtime_format_string(const _Runtime_format_string&) = delete;
     96       void operator=(const _Runtime_format_string&) = delete;
     97 
     98     private:
     99       basic_string_view<_CharT> _M_str;
    100 
    101       template<typename, typename...> friend struct std::basic_format_string;
    102     };
    103 } // namespace __format
    104 /// @endcond
    105 
    106   using format_context  = __format::__format_context<char>;
    107 #ifdef _GLIBCXX_USE_WCHAR_T
    108   using wformat_context = __format::__format_context<wchar_t>;
    109 #endif
    110 
    111   // [format.args], class template basic_format_args
    112   template<typename _Context> class basic_format_args;
    113   using format_args = basic_format_args<format_context>;
    114 #ifdef _GLIBCXX_USE_WCHAR_T
    115   using wformat_args = basic_format_args<wformat_context>;
    116 #endif
    117 
    118   // [format.arguments], arguments
    119   // [format.arg], class template basic_format_arg
    120   template<typename _Context>
    121     class basic_format_arg;
    122 
    123   /** A compile-time checked format string for the specified argument types.
    124    *
    125    * @since C++23 but available as an extension in C++20.
    126    */
    127   template<typename _CharT, typename... _Args>
    128     struct basic_format_string
    129     {
    130       template<typename _Tp>
    131 	requires convertible_to<const _Tp&, basic_string_view<_CharT>>
    132 	consteval
    133 	basic_format_string(const _Tp& __s);
    134 
    135       [[__gnu__::__always_inline__]]
    136       basic_format_string(__format::_Runtime_format_string<_CharT> __s) noexcept
    137       : _M_str(__s._M_str)
    138       { }
    139 
    140       [[__gnu__::__always_inline__]]
    141       constexpr basic_string_view<_CharT>
    142       get() const noexcept
    143       { return _M_str; }
    144 
    145     private:
    146       basic_string_view<_CharT> _M_str;
    147     };
    148 
    149   template<typename... _Args>
    150     using format_string = basic_format_string<char, type_identity_t<_Args>...>;
    151 
    152 #ifdef _GLIBCXX_USE_WCHAR_T
    153   template<typename... _Args>
    154     using wformat_string
    155       = basic_format_string<wchar_t, type_identity_t<_Args>...>;
    156 #endif
    157 
    158 #if __cplusplus > 202302L
    159   [[__gnu__::__always_inline__]]
    160   inline __format::_Runtime_format_string<char>
    161   runtime_format(string_view __fmt) noexcept
    162   { return __fmt; }
    163 
    164 #ifdef _GLIBCXX_USE_WCHAR_T
    165   [[__gnu__::__always_inline__]]
    166   inline __format::_Runtime_format_string<wchar_t>
    167   runtime_format(wstring_view __fmt) noexcept
    168   { return __fmt; }
    169 #endif
    170 #endif // C++26
    171 
    172   // [format.formatter], formatter
    173 
    174   /// The primary template of std::formatter is disabled.
    175   template<typename _Tp, typename _CharT = char>
    176     struct formatter
    177     {
    178       formatter() = delete; // No std::formatter specialization for this type.
    179       formatter(const formatter&) = delete;
    180       formatter& operator=(const formatter&) = delete;
    181     };
    182 
    183   // [format.error], class format_error
    184   class format_error : public runtime_error
    185   {
    186   public:
    187     explicit format_error(const string& __what) : runtime_error(__what) { }
    188     explicit format_error(const char* __what) : runtime_error(__what) { }
    189   };
    190 
    191   /// @cond undocumented
    192   [[noreturn]]
    193   inline void
    194   __throw_format_error(const char* __what)
    195   { _GLIBCXX_THROW_OR_ABORT(format_error(__what)); }
    196 
    197 namespace __format
    198 {
    199   // XXX use named functions for each constexpr error?
    200 
    201   [[noreturn]]
    202   inline void
    203   __unmatched_left_brace_in_format_string()
    204   { __throw_format_error("format error: unmatched '{' in format string"); }
    205 
    206   [[noreturn]]
    207   inline void
    208   __unmatched_right_brace_in_format_string()
    209   { __throw_format_error("format error: unmatched '}' in format string"); }
    210 
    211   [[noreturn]]
    212   inline void
    213   __conflicting_indexing_in_format_string()
    214   { __throw_format_error("format error: conflicting indexing style in format string"); }
    215 
    216   [[noreturn]]
    217   inline void
    218   __invalid_arg_id_in_format_string()
    219   { __throw_format_error("format error: invalid arg-id in format string"); }
    220 
    221   [[noreturn]]
    222   inline void
    223   __failed_to_parse_format_spec()
    224   { __throw_format_error("format error: failed to parse format-spec"); }
    225 } // namespace __format
    226   /// @endcond
    227 
    228   // [format.parse.ctx], class template basic_format_parse_context
    229   template<typename _CharT> class basic_format_parse_context;
    230   using format_parse_context = basic_format_parse_context<char>;
    231 #ifdef _GLIBCXX_USE_WCHAR_T
    232   using wformat_parse_context = basic_format_parse_context<wchar_t>;
    233 #endif
    234 
    235   template<typename _CharT>
    236     class basic_format_parse_context
    237     {
    238     public:
    239       using char_type = _CharT;
    240       using const_iterator = typename basic_string_view<_CharT>::const_iterator;
    241       using iterator = const_iterator;
    242 
    243       constexpr explicit
    244       basic_format_parse_context(basic_string_view<_CharT> __fmt,
    245 				 size_t __num_args = 0) noexcept
    246       : _M_begin(__fmt.begin()), _M_end(__fmt.end()), _M_num_args(__num_args)
    247       { }
    248 
    249       basic_format_parse_context(const basic_format_parse_context&) = delete;
    250       void operator=(const basic_format_parse_context&) = delete;
    251 
    252       constexpr const_iterator begin() const noexcept { return _M_begin; }
    253       constexpr const_iterator end() const noexcept { return _M_end; }
    254 
    255       constexpr void
    256       advance_to(const_iterator __it) noexcept
    257       { _M_begin = __it; }
    258 
    259       constexpr size_t
    260       next_arg_id()
    261       {
    262 	if (_M_indexing == _Manual)
    263 	  __format::__conflicting_indexing_in_format_string();
    264 	_M_indexing = _Auto;
    265 
    266 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
    267 	// 3825. Missing compile-time argument id check in next_arg_id
    268 	if (std::is_constant_evaluated())
    269 	  if (_M_next_arg_id == _M_num_args)
    270 	    __format::__invalid_arg_id_in_format_string();
    271 	return _M_next_arg_id++;
    272       }
    273 
    274       constexpr void
    275       check_arg_id(size_t __id)
    276       {
    277 	if (_M_indexing == _Auto)
    278 	  __format::__conflicting_indexing_in_format_string();
    279 	_M_indexing = _Manual;
    280 
    281 	if (std::is_constant_evaluated())
    282 	  if (__id >= _M_num_args)
    283 	    __format::__invalid_arg_id_in_format_string();
    284       }
    285 
    286     private:
    287       iterator _M_begin;
    288       iterator _M_end;
    289       enum _Indexing { _Unknown, _Manual, _Auto };
    290       _Indexing _M_indexing = _Unknown;
    291       size_t _M_next_arg_id = 0;
    292       size_t _M_num_args;
    293     };
    294 
    295 /// @cond undocumented
    296   template<typename _Tp, template<typename...> class _Class>
    297     static constexpr bool __is_specialization_of = false;
    298   template<template<typename...> class _Class, typename... _Args>
    299     static constexpr bool __is_specialization_of<_Class<_Args...>, _Class>
    300       = true;
    301 
    302 namespace __format
    303 {
    304   // pre: first != last
    305   template<typename _CharT>
    306     constexpr pair<unsigned short, const _CharT*>
    307     __parse_integer(const _CharT* __first, const _CharT* __last)
    308     {
    309       if (__first == __last)
    310 	__builtin_unreachable();
    311 
    312       if constexpr (is_same_v<_CharT, char>)
    313 	{
    314 	  const auto __start = __first;
    315 	  unsigned short __val = 0;
    316 	  // N.B. std::from_chars is not constexpr in C++20.
    317 	  if (__detail::__from_chars_alnum<true>(__first, __last, __val, 10)
    318 		&& __first != __start) [[likely]]
    319 	    return {__val, __first};
    320 	}
    321       else
    322 	{
    323 	  constexpr int __n = 32;
    324 	  char __buf[__n]{};
    325 	  for (int __i = 0; __i < __n && (__first + __i) != __last; ++__i)
    326 	    __buf[__i] = __first[__i];
    327 	  auto [__v, __ptr] = __format::__parse_integer(__buf, __buf + __n);
    328 	  if (__ptr) [[likely]]
    329 	    return {__v, __first + (__ptr - __buf)};
    330 	}
    331       return {0, nullptr};
    332     }
    333 
    334   template<typename _CharT>
    335     constexpr pair<unsigned short, const _CharT*>
    336     __parse_arg_id(const _CharT* __first, const _CharT* __last)
    337     {
    338       if (__first == __last)
    339 	__builtin_unreachable();
    340 
    341       if (*__first == '0')
    342 	return {0, __first + 1}; // No leading zeros allowed, so '0...' == 0
    343 
    344       if ('1' <= *__first && *__first <= '9')
    345 	{
    346 	  const unsigned short __id = *__first - '0';
    347 	  const auto __next = __first + 1;
    348 	  // Optimize for most likely case of single digit arg-id.
    349 	  if (__next == __last || !('0' <= *__next && *__next <= '9'))
    350 	    return {__id, __next};
    351 	  else
    352 	    return __format::__parse_integer(__first, __last);
    353 	}
    354       return {0, nullptr};
    355     }
    356 
    357   enum _Pres_type {
    358     _Pres_none = 0, // Default type (not valid for integer presentation types).
    359     // Presentation types for integral types (including bool and charT).
    360     _Pres_d = 1, _Pres_b, _Pres_B, _Pres_o, _Pres_x, _Pres_X, _Pres_c,
    361     // Presentation types for floating-point types.
    362     _Pres_a = 1, _Pres_A, _Pres_e, _Pres_E, _Pres_f, _Pres_F, _Pres_g, _Pres_G,
    363     _Pres_p = 0, _Pres_P,   // For pointers.
    364     _Pres_s = 0,            // For strings and bool.
    365     _Pres_esc = 0xf,        // For strings and charT.
    366   };
    367 
    368   enum _Align {
    369     _Align_default,
    370     _Align_left,
    371     _Align_right,
    372     _Align_centre,
    373   };
    374 
    375   enum _Sign {
    376     _Sign_default,
    377     _Sign_plus,
    378     _Sign_minus,  // XXX does this need to be distinct from _Sign_default?
    379     _Sign_space,
    380   };
    381 
    382   enum _WidthPrec {
    383     _WP_none,    // No width/prec specified.
    384     _WP_value,   // Fixed width/prec specified.
    385     _WP_from_arg // Use a formatting argument for width/prec.
    386   };
    387 
    388   template<typename _Context>
    389     size_t
    390     __int_from_arg(const basic_format_arg<_Context>& __arg);
    391 
    392   constexpr bool __is_digit(char __c)
    393   { return std::__detail::__from_chars_alnum_to_val(__c) < 10; }
    394 
    395   constexpr bool __is_xdigit(char __c)
    396   { return std::__detail::__from_chars_alnum_to_val(__c) < 16; }
    397 
    398   template<typename _CharT>
    399     struct _Spec
    400     {
    401       _Align     _M_align : 2;
    402       _Sign      _M_sign : 2;
    403       unsigned   _M_alt : 1;
    404       unsigned   _M_localized : 1;
    405       unsigned   _M_zero_fill : 1;
    406       _WidthPrec _M_width_kind : 2;
    407       _WidthPrec _M_prec_kind : 2;
    408       _Pres_type _M_type : 4;
    409       unsigned   _M_reserved : 1;
    410       unsigned   _M_reserved2 : 16;
    411       unsigned short _M_width;
    412       unsigned short _M_prec;
    413       char32_t _M_fill = ' ';
    414 
    415       using iterator = typename basic_string_view<_CharT>::iterator;
    416 
    417       static constexpr _Align
    418       _S_align(_CharT __c) noexcept
    419       {
    420 	switch (__c)
    421 	{
    422 	  case '<': return _Align_left;
    423 	  case '>': return _Align_right;
    424 	  case '^': return _Align_centre;
    425 	  default: return _Align_default;
    426 	}
    427       }
    428 
    429       // pre: __first != __last
    430       constexpr iterator
    431       _M_parse_fill_and_align(iterator __first, iterator __last) noexcept
    432       {
    433 	if (*__first != '{')
    434 	  {
    435 	    using namespace __unicode;
    436 	    if constexpr (__literal_encoding_is_unicode<_CharT>())
    437 	      {
    438 		// Accept any UCS scalar value as fill character.
    439 		_Utf32_view<ranges::subrange<iterator>> __uv({__first, __last});
    440 		if (!__uv.empty())
    441 		  {
    442 		    auto __beg = __uv.begin();
    443 		    char32_t __c = *__beg++;
    444 		    if (__is_scalar_value(__c))
    445 		      if (auto __next = __beg.base(); __next != __last)
    446 			if (_Align __align = _S_align(*__next))
    447 			  {
    448 			    _M_fill = __c;
    449 			    _M_align = __align;
    450 			    return ++__next;
    451 			  }
    452 		  }
    453 	      }
    454 	    else if (__last - __first >= 2)
    455 	      if (_Align __align = _S_align(__first[1]))
    456 		{
    457 		  _M_fill = *__first;
    458 		  _M_align = __align;
    459 		  return __first + 2;
    460 		}
    461 
    462 	    if (_Align __align = _S_align(__first[0]))
    463 	      {
    464 		_M_fill = ' ';
    465 		_M_align = __align;
    466 		return __first + 1;
    467 	      }
    468 	  }
    469 	return __first;
    470       }
    471 
    472       static constexpr _Sign
    473       _S_sign(_CharT __c) noexcept
    474       {
    475 	switch (__c)
    476 	{
    477 	  case '+': return _Sign_plus;
    478 	  case '-': return _Sign_minus;
    479 	  case ' ': return _Sign_space;
    480 	  default:  return _Sign_default;
    481 	}
    482       }
    483 
    484       // pre: __first != __last
    485       constexpr iterator
    486       _M_parse_sign(iterator __first, iterator) noexcept
    487       {
    488 	if (_Sign __sign = _S_sign(*__first))
    489 	  {
    490 	    _M_sign = __sign;
    491 	    return __first + 1;
    492 	  }
    493 	return __first;
    494       }
    495 
    496       // pre: *__first is valid
    497       constexpr iterator
    498       _M_parse_alternate_form(iterator __first, iterator) noexcept
    499       {
    500 	if (*__first == '#')
    501 	  {
    502 	    _M_alt = true;
    503 	    ++__first;
    504 	  }
    505 	return __first;
    506       }
    507 
    508       // pre: __first != __last
    509       constexpr iterator
    510       _M_parse_zero_fill(iterator __first, iterator /* __last */) noexcept
    511       {
    512 	if (*__first == '0')
    513 	  {
    514 	    _M_zero_fill = true;
    515 	    ++__first;
    516 	  }
    517 	return __first;
    518       }
    519 
    520       // pre: __first != __last
    521       static constexpr iterator
    522       _S_parse_width_or_precision(iterator __first, iterator __last,
    523 				  unsigned short& __val, bool& __arg_id,
    524 				  basic_format_parse_context<_CharT>& __pc)
    525       {
    526 	if (__format::__is_digit(*__first))
    527 	  {
    528 	    auto [__v, __ptr] = __format::__parse_integer(__first, __last);
    529 	    if (!__ptr)
    530 	      __throw_format_error("format error: invalid width or precision "
    531 				   "in format-spec");
    532 	    __first = __ptr;
    533 	    __val = __v;
    534 	  }
    535 	else if (*__first == '{')
    536 	  {
    537 	    __arg_id = true;
    538 	    ++__first;
    539 	    if (__first == __last)
    540 	      __format::__unmatched_left_brace_in_format_string();
    541 	    if (*__first == '}')
    542 	      __val = __pc.next_arg_id();
    543 	    else
    544 	      {
    545 		auto [__v, __ptr] = __format::__parse_arg_id(__first, __last);
    546 		if (__ptr == nullptr || __ptr == __last || *__ptr != '}')
    547 		  __format::__invalid_arg_id_in_format_string();
    548 		__first = __ptr;
    549 		__pc.check_arg_id(__v);
    550 		__val = __v;
    551 	      }
    552 	    ++__first; // past the '}'
    553 	  }
    554 	return __first;
    555       }
    556 
    557       // pre: __first != __last
    558       constexpr iterator
    559       _M_parse_width(iterator __first, iterator __last,
    560 		     basic_format_parse_context<_CharT>& __pc)
    561       {
    562 	bool __arg_id = false;
    563 	if (*__first == '0')
    564 	  __throw_format_error("format error: width must be non-zero in "
    565 			       "format string");
    566 	auto __next = _S_parse_width_or_precision(__first, __last, _M_width,
    567 						  __arg_id, __pc);
    568 	if (__next != __first)
    569 	  _M_width_kind = __arg_id ? _WP_from_arg : _WP_value;
    570 	return __next;
    571       }
    572 
    573       // pre: __first != __last
    574       constexpr iterator
    575       _M_parse_precision(iterator __first, iterator __last,
    576 			 basic_format_parse_context<_CharT>& __pc)
    577       {
    578 	if (__first[0] != '.')
    579 	  return __first;
    580 
    581 	iterator __next = ++__first;
    582 	bool __arg_id = false;
    583 	if (__next != __last)
    584 	  __next = _S_parse_width_or_precision(__first, __last, _M_prec,
    585 					       __arg_id, __pc);
    586 	if (__next == __first)
    587 	  __throw_format_error("format error: missing precision after '.' in "
    588 			       "format string");
    589 	_M_prec_kind = __arg_id ? _WP_from_arg : _WP_value;
    590 	return __next;
    591       }
    592 
    593       // pre: __first != __last
    594       constexpr iterator
    595       _M_parse_locale(iterator __first, iterator /* __last */) noexcept
    596       {
    597 	if (*__first == 'L')
    598 	  {
    599 	    _M_localized = true;
    600 	    ++__first;
    601 	  }
    602 	return __first;
    603       }
    604 
    605       template<typename _Context>
    606 	size_t
    607 	_M_get_width(_Context& __ctx) const
    608 	{
    609 	  size_t __width = 0;
    610 	  if (_M_width_kind == _WP_value)
    611 	    __width = _M_width;
    612 	  else if (_M_width_kind == _WP_from_arg)
    613 	    __width = __format::__int_from_arg(__ctx.arg(_M_width));
    614 	  return __width;
    615 	}
    616 
    617       template<typename _Context>
    618 	size_t
    619 	_M_get_precision(_Context& __ctx) const
    620 	{
    621 	  size_t __prec = -1;
    622 	  if (_M_prec_kind == _WP_value)
    623 	    __prec = _M_prec;
    624 	  else if (_M_prec_kind == _WP_from_arg)
    625 	    __prec = __format::__int_from_arg(__ctx.arg(_M_prec));
    626 	  return __prec;
    627 	}
    628     };
    629 
    630   template<typename _Int>
    631     inline char*
    632     __put_sign(_Int __i, _Sign __sign, char* __dest) noexcept
    633     {
    634       if (__i < 0)
    635 	*__dest = '-';
    636       else if (__sign == _Sign_plus)
    637 	*__dest = '+';
    638       else if (__sign == _Sign_space)
    639 	*__dest = ' ';
    640       else
    641 	++__dest;
    642       return __dest;
    643     }
    644 
    645   // Write STR to OUT (and do so efficiently if OUT is a _Sink_iter).
    646   template<typename _Out, typename _CharT>
    647     requires output_iterator<_Out, const _CharT&>
    648     inline _Out
    649     __write(_Out __out, basic_string_view<_CharT> __str)
    650     {
    651       if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
    652 	{
    653 	  if (__str.size())
    654 	    __out = __str;
    655 	}
    656       else
    657 	for (_CharT __c : __str)
    658 	  *__out++ = __c;
    659       return __out;
    660     }
    661 
    662   // Write STR to OUT with NFILL copies of FILL_CHAR specified by ALIGN.
    663   // pre: __align != _Align_default
    664   template<typename _Out, typename _CharT>
    665     _Out
    666     __write_padded(_Out __out, basic_string_view<_CharT> __str,
    667 		   _Align __align, size_t __nfill, char32_t __fill_char)
    668     {
    669       const size_t __buflen = 0x20;
    670       _CharT __padding_chars[__buflen];
    671       __padding_chars[0] = _CharT();
    672       basic_string_view<_CharT> __padding{__padding_chars, __buflen};
    673 
    674       auto __pad = [&__padding] (size_t __n, _Out& __o) {
    675 	if (__n == 0)
    676 	  return;
    677 	while (__n > __padding.size())
    678 	  {
    679 	    __o = __format::__write(std::move(__o), __padding);
    680 	    __n -= __padding.size();
    681 	  }
    682 	if (__n != 0)
    683 	  __o = __format::__write(std::move(__o), __padding.substr(0, __n));
    684       };
    685 
    686       size_t __l, __r, __max;
    687       if (__align == _Align_centre)
    688 	{
    689 	  __l = __nfill / 2;
    690 	  __r = __l + (__nfill & 1);
    691 	  __max = __r;
    692 	}
    693       else if (__align == _Align_right)
    694 	{
    695 	  __l = __nfill;
    696 	  __r = 0;
    697 	  __max = __l;
    698 	}
    699       else
    700 	{
    701 	  __l = 0;
    702 	  __r = __nfill;
    703 	  __max = __r;
    704 	}
    705 
    706       using namespace __unicode;
    707       if constexpr (__literal_encoding_is_unicode<_CharT>())
    708 	if (!__is_single_code_unit<_CharT>(__fill_char)) [[unlikely]]
    709 	  {
    710 	    // Encode fill char as multiple code units of type _CharT.
    711 	    const char32_t __arr[1]{ __fill_char };
    712 	    _Utf_view<_CharT, const char32_t(&)[1]> __v(__arr);
    713 	    basic_string<_CharT> __padstr(__v.begin(), __v.end());
    714 	    __padding = __padstr;
    715 	    while (__l-- > 0)
    716 	      __out = __format::__write(std::move(__out), __padding);
    717 	    __out = __format::__write(std::move(__out), __str);
    718 	    while (__r-- > 0)
    719 	      __out = __format::__write(std::move(__out), __padding);
    720 	    return __out;
    721 	  }
    722 
    723       if (__max < __buflen)
    724 	__padding.remove_suffix(__buflen - __max);
    725       else
    726 	__max = __buflen;
    727 
    728       char_traits<_CharT>::assign(__padding_chars, __max, __fill_char);
    729       __pad(__l, __out);
    730       __out = __format::__write(std::move(__out), __str);
    731       __pad(__r, __out);
    732 
    733       return __out;
    734     }
    735 
    736   // Write STR to OUT, with alignment and padding as determined by SPEC.
    737   // pre: __spec._M_align != _Align_default || __align != _Align_default
    738   template<typename _CharT, typename _Out>
    739     _Out
    740     __write_padded_as_spec(basic_string_view<type_identity_t<_CharT>> __str,
    741 			   size_t __estimated_width,
    742 			   basic_format_context<_Out, _CharT>& __fc,
    743 			   const _Spec<_CharT>& __spec,
    744 			   _Align __align = _Align_left)
    745     {
    746       size_t __width = __spec._M_get_width(__fc);
    747 
    748       if (__width <= __estimated_width)
    749 	return __format::__write(__fc.out(), __str);
    750 
    751       const size_t __nfill = __width - __estimated_width;
    752 
    753       if (__spec._M_align)
    754 	__align = __spec._M_align;
    755 
    756       return __format::__write_padded(__fc.out(), __str, __align, __nfill,
    757 				      __spec._M_fill);
    758     }
    759 
    760   // A lightweight optional<locale>.
    761   struct _Optional_locale
    762   {
    763     [[__gnu__::__always_inline__]]
    764     _Optional_locale() : _M_dummy(), _M_hasval(false) { }
    765 
    766     _Optional_locale(const locale& __loc) noexcept
    767     : _M_loc(__loc), _M_hasval(true)
    768     { }
    769 
    770     _Optional_locale(const _Optional_locale& __l) noexcept
    771     : _M_dummy(), _M_hasval(__l._M_hasval)
    772     {
    773       if (_M_hasval)
    774 	std::construct_at(&_M_loc, __l._M_loc);
    775     }
    776 
    777     _Optional_locale&
    778     operator=(const _Optional_locale& __l) noexcept
    779     {
    780       if (_M_hasval)
    781 	{
    782 	  if (__l._M_hasval)
    783 	    _M_loc = __l._M_loc;
    784 	  else
    785 	    {
    786 	      _M_loc.~locale();
    787 	      _M_hasval = false;
    788 	    }
    789 	}
    790       else if (__l._M_hasval)
    791 	{
    792 	  std::construct_at(&_M_loc, __l._M_loc);
    793 	  _M_hasval = true;
    794 	}
    795       return *this;
    796     }
    797 
    798     ~_Optional_locale() { if (_M_hasval) _M_loc.~locale(); }
    799 
    800     _Optional_locale&
    801     operator=(locale&& __loc) noexcept
    802     {
    803       if (_M_hasval)
    804 	_M_loc = std::move(__loc);
    805       else
    806 	{
    807 	  std::construct_at(&_M_loc, std::move(__loc));
    808 	  _M_hasval = true;
    809 	}
    810       return *this;
    811     }
    812 
    813     const locale&
    814     value() noexcept
    815     {
    816       if (!_M_hasval)
    817 	{
    818 	  std::construct_at(&_M_loc);
    819 	  _M_hasval = true;
    820 	}
    821       return _M_loc;
    822     }
    823 
    824     bool has_value() const noexcept { return _M_hasval; }
    825 
    826     union {
    827       char _M_dummy = '\0';
    828       std::locale _M_loc;
    829     };
    830     bool _M_hasval = false;
    831   };
    832 
    833 #ifdef _GLIBCXX_USE_WCHAR_T
    834   template<typename _CharT>
    835     concept __char = same_as<_CharT, char> || same_as<_CharT, wchar_t>;
    836 #else
    837   template<typename _CharT>
    838     concept __char = same_as<_CharT, char>;
    839 #endif
    840 
    841   template<__char _CharT>
    842     struct __formatter_str
    843     {
    844       constexpr typename basic_format_parse_context<_CharT>::iterator
    845       parse(basic_format_parse_context<_CharT>& __pc)
    846       {
    847 	auto __first = __pc.begin();
    848 	const auto __last = __pc.end();
    849 	_Spec<_CharT> __spec{};
    850 
    851 	auto __finalize = [this, &__spec] {
    852 	  _M_spec = __spec;
    853 	};
    854 
    855 	auto __finished = [&] {
    856 	  if (__first == __last || *__first == '}')
    857 	    {
    858 	      __finalize();
    859 	      return true;
    860 	    }
    861 	  return false;
    862 	};
    863 
    864 	if (__finished())
    865 	  return __first;
    866 
    867 	__first = __spec._M_parse_fill_and_align(__first, __last);
    868 	if (__finished())
    869 	  return __first;
    870 
    871 	__first = __spec._M_parse_width(__first, __last, __pc);
    872 	if (__finished())
    873 	  return __first;
    874 
    875 	__first = __spec._M_parse_precision(__first, __last, __pc);
    876 	if (__finished())
    877 	  return __first;
    878 
    879 	if (*__first == 's')
    880 	  ++__first;
    881 #if __cpp_lib_format_ranges
    882 	else if (*__first == '?')
    883 	  {
    884 	    __spec._M_type = _Pres_esc;
    885 	    ++__first;
    886 	  }
    887 #endif
    888 
    889 	if (__finished())
    890 	  return __first;
    891 
    892 	__format::__failed_to_parse_format_spec();
    893       }
    894 
    895       template<typename _Out>
    896 	_Out
    897 	format(basic_string_view<_CharT> __s,
    898 	       basic_format_context<_Out, _CharT>& __fc) const
    899 	{
    900 	  if (_M_spec._M_type == _Pres_esc)
    901 	    {
    902 	      // TODO: C++23 escaped string presentation
    903 	    }
    904 
    905 	  if (_M_spec._M_width_kind == _WP_none
    906 		&& _M_spec._M_prec_kind == _WP_none)
    907 	    return __format::__write(__fc.out(), __s);
    908 
    909 	  size_t __estimated_width;
    910 	  if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
    911 	    {
    912 	      if (_M_spec._M_prec_kind != _WP_none)
    913 		{
    914 		  size_t __prec = _M_spec._M_get_precision(__fc);
    915 		  __estimated_width = __unicode::__truncate(__s, __prec);
    916 		}
    917 	      else
    918 		__estimated_width = __unicode::__field_width(__s);
    919 	    }
    920 	  else
    921 	    {
    922 	      __s = __s.substr(0, _M_spec._M_get_precision(__fc));
    923 	      __estimated_width = __s.size();
    924 	    }
    925 
    926 	  return __format::__write_padded_as_spec(__s, __estimated_width,
    927 						  __fc, _M_spec);
    928 	}
    929 
    930 #if __cpp_lib_format_ranges
    931       constexpr void
    932       set_debug_format() noexcept
    933       { _M_spec._M_type = _Pres_esc; }
    934 #endif
    935 
    936     private:
    937       _Spec<_CharT> _M_spec{};
    938     };
    939 
    940   template<__char _CharT>
    941     struct __formatter_int
    942     {
    943       // If no presentation type is specified, meaning of "none" depends
    944       // whether we are formatting an integer or a char or a bool.
    945       static constexpr _Pres_type _AsInteger = _Pres_d;
    946       static constexpr _Pres_type _AsBool = _Pres_s;
    947       static constexpr _Pres_type _AsChar = _Pres_c;
    948 
    949       constexpr typename basic_format_parse_context<_CharT>::iterator
    950       _M_do_parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type)
    951       {
    952 	_Spec<_CharT> __spec{};
    953 	__spec._M_type = __type;
    954 
    955 	const auto __last = __pc.end();
    956 	auto __first = __pc.begin();
    957 
    958 	auto __finalize = [this, &__spec] {
    959 	  _M_spec = __spec;
    960 	};
    961 
    962 	auto __finished = [&] {
    963 	  if (__first == __last || *__first == '}')
    964 	    {
    965 	      __finalize();
    966 	      return true;
    967 	    }
    968 	  return false;
    969 	};
    970 
    971 	if (__finished())
    972 	  return __first;
    973 
    974 	__first = __spec._M_parse_fill_and_align(__first, __last);
    975 	if (__finished())
    976 	  return __first;
    977 
    978 	__first = __spec._M_parse_sign(__first, __last);
    979 	if (__finished())
    980 	  return __first;
    981 
    982 	__first = __spec._M_parse_alternate_form(__first, __last);
    983 	if (__finished())
    984 	  return __first;
    985 
    986 	__first = __spec._M_parse_zero_fill(__first, __last);
    987 	if (__finished())
    988 	  return __first;
    989 
    990 	__first = __spec._M_parse_width(__first, __last, __pc);
    991 	if (__finished())
    992 	  return __first;
    993 
    994 	__first = __spec._M_parse_locale(__first, __last);
    995 	if (__finished())
    996 	  return __first;
    997 
    998 	switch (*__first)
    999 	{
   1000 	  case 'b':
   1001 	    __spec._M_type = _Pres_b;
   1002 	    ++__first;
   1003 	    break;
   1004 	  case 'B':
   1005 	    __spec._M_type = _Pres_B;
   1006 	    ++__first;
   1007 	    break;
   1008 	  case 'c':
   1009 	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1010 	    // 3586. format should not print bool with 'c'
   1011 	    if (__type != _AsBool)
   1012 	      {
   1013 		__spec._M_type = _Pres_c;
   1014 		++__first;
   1015 	      }
   1016 	    break;
   1017 	  case 'd':
   1018 	    __spec._M_type = _Pres_d;
   1019 	    ++__first;
   1020 	    break;
   1021 	  case 'o':
   1022 	    __spec._M_type = _Pres_o;
   1023 	    ++__first;
   1024 	    break;
   1025 	  case 'x':
   1026 	    __spec._M_type = _Pres_x;
   1027 	    ++__first;
   1028 	    break;
   1029 	  case 'X':
   1030 	    __spec._M_type = _Pres_X;
   1031 	    ++__first;
   1032 	    break;
   1033 	  case 's':
   1034 	    if (__type == _AsBool)
   1035 	      {
   1036 		__spec._M_type = _Pres_s; // same value (and meaning) as "none"
   1037 		++__first;
   1038 	      }
   1039 	    break;
   1040 #if __cpp_lib_format_ranges
   1041 	  case '?':
   1042 	    if (__type == _AsChar)
   1043 	      {
   1044 		__spec._M_type = _Pres_esc;
   1045 		++__first;
   1046 	      }
   1047 #endif
   1048 	    break;
   1049 	  }
   1050 
   1051 	if (__finished())
   1052 	  return __first;
   1053 
   1054 	__format::__failed_to_parse_format_spec();
   1055       }
   1056 
   1057       template<typename _Tp>
   1058 	constexpr typename basic_format_parse_context<_CharT>::iterator
   1059 	_M_parse(basic_format_parse_context<_CharT>& __pc)
   1060 	{
   1061 	  if constexpr (is_same_v<_Tp, bool>)
   1062 	    {
   1063 	      auto __end = _M_do_parse(__pc, _AsBool);
   1064 	      if (_M_spec._M_type == _Pres_s)
   1065 		if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill)
   1066 		  __throw_format_error("format error: format-spec contains "
   1067 				       "invalid formatting options for "
   1068 				       "'bool'");
   1069 	      return __end;
   1070 	    }
   1071 	  else if constexpr (__char<_Tp>)
   1072 	    {
   1073 	      auto __end = _M_do_parse(__pc, _AsChar);
   1074 	      if (_M_spec._M_type == _Pres_c || _M_spec._M_type == _Pres_esc)
   1075 		if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill
   1076 		      /* XXX should be invalid? || _M_spec._M_localized */)
   1077 		  __throw_format_error("format error: format-spec contains "
   1078 				       "invalid formatting options for "
   1079 				       "'charT'");
   1080 	      return __end;
   1081 	    }
   1082 	  else
   1083 	    return _M_do_parse(__pc, _AsInteger);
   1084 	}
   1085 
   1086       template<typename _Int, typename _Out>
   1087 	typename basic_format_context<_Out, _CharT>::iterator
   1088 	format(_Int __i, basic_format_context<_Out, _CharT>& __fc) const
   1089 	{
   1090 	  if (_M_spec._M_type == _Pres_c)
   1091 	    return _M_format_character(_S_to_character(__i), __fc);
   1092 
   1093 	  char __buf[sizeof(_Int) * __CHAR_BIT__ + 3];
   1094 	  to_chars_result __res{};
   1095 
   1096 	  string_view __base_prefix;
   1097 	  make_unsigned_t<_Int> __u;
   1098 	  if (__i < 0)
   1099 	    __u = -static_cast<make_unsigned_t<_Int>>(__i);
   1100 	  else
   1101 	    __u = __i;
   1102 
   1103 	  char* __start = __buf + 3;
   1104 	  char* const __end = __buf + sizeof(__buf);
   1105 	  char* const __start_digits = __start;
   1106 
   1107 	  switch (_M_spec._M_type)
   1108 	  {
   1109 	    case _Pres_b:
   1110 	    case _Pres_B:
   1111 	      __base_prefix = _M_spec._M_type == _Pres_b ? "0b" : "0B";
   1112 	      __res = to_chars(__start, __end, __u, 2);
   1113 	      break;
   1114 #if 0
   1115 	    case _Pres_c:
   1116 	      return _M_format_character(_S_to_character(__i), __fc);
   1117 #endif
   1118 	    case _Pres_none:
   1119 	      // Should not reach here with _Pres_none for bool or charT, so:
   1120 	      [[fallthrough]];
   1121 	    case _Pres_d:
   1122 	      __res = to_chars(__start, __end, __u, 10);
   1123 	      break;
   1124 	    case _Pres_o:
   1125 	      if (__i != 0)
   1126 		__base_prefix = "0";
   1127 	      __res = to_chars(__start, __end, __u, 8);
   1128 	      break;
   1129 	    case _Pres_x:
   1130 	    case _Pres_X:
   1131 	      __base_prefix = _M_spec._M_type == _Pres_x ? "0x" : "0X";
   1132 	      __res = to_chars(__start, __end, __u, 16);
   1133 	      if (_M_spec._M_type == _Pres_X)
   1134 		for (auto __p = __start; __p != __res.ptr; ++__p)
   1135 #if __has_builtin(__builtin_toupper)
   1136 		  *__p = __builtin_toupper(*__p);
   1137 #else
   1138 		  *__p = std::toupper(*__p);
   1139 #endif
   1140 	      break;
   1141 	    default:
   1142 	      __builtin_unreachable();
   1143 	  }
   1144 
   1145 	  if (_M_spec._M_alt && __base_prefix.size())
   1146 	    {
   1147 	      __start -= __base_prefix.size();
   1148 	      __builtin_memcpy(__start, __base_prefix.data(),
   1149 			       __base_prefix.size());
   1150 	    }
   1151 	  __start = __format::__put_sign(__i, _M_spec._M_sign, __start - 1);
   1152 
   1153 	  return _M_format_int(string_view(__start, __res.ptr - __start),
   1154 			       __start_digits - __start, __fc);
   1155 	}
   1156 
   1157       template<typename _Out>
   1158 	typename basic_format_context<_Out, _CharT>::iterator
   1159 	format(bool __i, basic_format_context<_Out, _CharT>& __fc) const
   1160 	{
   1161 	  if (_M_spec._M_type == _Pres_c)
   1162 	    return _M_format_character(static_cast<unsigned char>(__i), __fc);
   1163 	  if (_M_spec._M_type != _Pres_s)
   1164 	    return format(static_cast<unsigned char>(__i), __fc);
   1165 
   1166 	  basic_string<_CharT> __s;
   1167 	  size_t __est_width;
   1168 	  if (_M_spec._M_localized) [[unlikely]]
   1169 	    {
   1170 	      auto& __np = std::use_facet<numpunct<_CharT>>(__fc.locale());
   1171 	      __s = __i ? __np.truename() : __np.falsename();
   1172 	      __est_width = __s.size(); // TODO Unicode-aware estimate
   1173 	    }
   1174 	  else
   1175 	    {
   1176 	      if constexpr (is_same_v<char, _CharT>)
   1177 		__s = __i ? "true" : "false";
   1178 	      else
   1179 		__s = __i ? L"true" : L"false";
   1180 	      __est_width = __s.size();
   1181 	    }
   1182 
   1183 	  return __format::__write_padded_as_spec(__s, __est_width, __fc,
   1184 						  _M_spec);
   1185 	}
   1186 
   1187       [[__gnu__::__always_inline__]]
   1188       static size_t
   1189       _S_character_width(_CharT __c)
   1190       {
   1191 	// N.B. single byte cannot encode charcter of width greater than 1
   1192 	if constexpr (sizeof(_CharT) > 1u && 
   1193 			__unicode::__literal_encoding_is_unicode<_CharT>())
   1194 	  return __unicode::__field_width(__c);
   1195 	else
   1196 	  return 1u;
   1197       }
   1198 
   1199       template<typename _Out>
   1200 	typename basic_format_context<_Out, _CharT>::iterator
   1201 	_M_format_character(_CharT __c,
   1202 		      basic_format_context<_Out, _CharT>& __fc) const
   1203 	{
   1204 	  return __format::__write_padded_as_spec({&__c, 1u},
   1205 						  _S_character_width(__c),
   1206 			                          __fc, _M_spec);
   1207 	}
   1208 
   1209       template<typename _Int>
   1210 	static _CharT
   1211 	_S_to_character(_Int __i)
   1212 	{
   1213 	  using _Traits = __gnu_cxx::__int_traits<_CharT>;
   1214 	  if constexpr (is_signed_v<_Int> == is_signed_v<_CharT>)
   1215 	    {
   1216 	      if (_Traits::__min <= __i && __i <= _Traits::__max)
   1217 		return static_cast<_CharT>(__i);
   1218 	    }
   1219 	  else if constexpr (is_signed_v<_Int>)
   1220 	    {
   1221 	      if (__i >= 0 && make_unsigned_t<_Int>(__i) <= _Traits::__max)
   1222 		return static_cast<_CharT>(__i);
   1223 	    }
   1224 	  else if (__i <= make_unsigned_t<_CharT>(_Traits::__max))
   1225 	    return static_cast<_CharT>(__i);
   1226 	  __throw_format_error("format error: integer not representable as "
   1227 			       "character");
   1228 	}
   1229 
   1230       template<typename _Out>
   1231 	typename basic_format_context<_Out, _CharT>::iterator
   1232 	_M_format_int(string_view __narrow_str, size_t __prefix_len,
   1233 		      basic_format_context<_Out, _CharT>& __fc) const
   1234 	{
   1235 	  size_t __width = _M_spec._M_get_width(__fc);
   1236 
   1237 	  basic_string_view<_CharT> __str;
   1238 	  if constexpr (is_same_v<char, _CharT>)
   1239 	    __str = __narrow_str;
   1240 #ifdef _GLIBCXX_USE_WCHAR_T
   1241 	  else
   1242 	    {
   1243 	      size_t __n = __narrow_str.size();
   1244 	      auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
   1245 	      std::__to_wstring_numeric(__narrow_str.data(), __n, __p);
   1246 	      __str = {__p, __n};
   1247 	    }
   1248 #endif
   1249 
   1250 	  if (_M_spec._M_localized)
   1251 	    {
   1252 	      const auto& __l = __fc.locale();
   1253 	      if (__l.name() != "C")
   1254 		{
   1255 		  auto& __np = use_facet<numpunct<_CharT>>(__l);
   1256 		  string __grp = __np.grouping();
   1257 		  if (!__grp.empty())
   1258 		    {
   1259 		      size_t __n = __str.size() - __prefix_len;
   1260 		      auto __p = (_CharT*)__builtin_alloca(2 * __n
   1261 							     * sizeof(_CharT)
   1262 							     + __prefix_len);
   1263 		      auto __s = __str.data();
   1264 		      char_traits<_CharT>::copy(__p, __s, __prefix_len);
   1265 		      __s += __prefix_len;
   1266 		      auto __end = std::__add_grouping(__p + __prefix_len,
   1267 						       __np.thousands_sep(),
   1268 						       __grp.data(),
   1269 						       __grp.size(),
   1270 						       __s, __s + __n);
   1271 		      __str = {__p, size_t(__end - __p)};
   1272 		    }
   1273 		}
   1274 	    }
   1275 
   1276 	  if (__width <= __str.size())
   1277 	    return __format::__write(__fc.out(), __str);
   1278 
   1279 	  char32_t __fill_char = _M_spec._M_fill;
   1280 	  _Align __align = _M_spec._M_align;
   1281 
   1282 	  size_t __nfill = __width - __str.size();
   1283 	  auto __out = __fc.out();
   1284 	  if (__align == _Align_default)
   1285 	    {
   1286 	      __align = _Align_right;
   1287 	      if (_M_spec._M_zero_fill)
   1288 		{
   1289 		  __fill_char = _CharT('0');
   1290 		  // Write sign and base prefix before zero filling.
   1291 		  if (__prefix_len != 0)
   1292 		    {
   1293 		      __out = __format::__write(std::move(__out),
   1294 						__str.substr(0, __prefix_len));
   1295 		      __str.remove_prefix(__prefix_len);
   1296 		    }
   1297 		}
   1298 	      else
   1299 		__fill_char = _CharT(' ');
   1300 	    }
   1301 	  return __format::__write_padded(std::move(__out), __str,
   1302 					  __align, __nfill, __fill_char);
   1303 	}
   1304 
   1305 #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
   1306       template<typename _Tp>
   1307 	using make_unsigned_t
   1308 	  = typename __conditional_t<(sizeof(_Tp) <= sizeof(long long)),
   1309 				     std::make_unsigned<_Tp>,
   1310 				     type_identity<unsigned __int128>>::type;
   1311 
   1312       // std::to_chars is not overloaded for int128 in strict mode.
   1313       template<typename _Int>
   1314 	static to_chars_result
   1315 	to_chars(char* __first, char* __last, _Int __value, int __base)
   1316 	{ return std::__to_chars_i<_Int>(__first, __last, __value, __base); }
   1317 #endif
   1318 
   1319       _Spec<_CharT> _M_spec{};
   1320     };
   1321 
   1322   // Decide how 128-bit floating-point types should be formatted (or not).
   1323   // When supported, the typedef __format::__float128_t is the type that
   1324   // format arguments should be converted to for storage in basic_format_arg.
   1325   // Define the macro _GLIBCXX_FORMAT_F128 to say they're supported.
   1326   // _GLIBCXX_FORMAT_F128=1 means __float128, _Float128 etc. will be formatted
   1327   // by converting them to long double (or __ieee128 for powerpc64le).
   1328   // _GLIBCXX_FORMAT_F128=2 means basic_format_arg needs to enable explicit
   1329   // support for _Float128, rather than formatting it as another type.
   1330 #undef _GLIBCXX_FORMAT_F128
   1331 
   1332 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
   1333 
   1334   // Format 128-bit floating-point types using __ieee128.
   1335   using __float128_t = __ieee128;
   1336 # define _GLIBCXX_FORMAT_F128 1
   1337 
   1338 #ifdef __LONG_DOUBLE_IEEE128__
   1339   // These overloads exist in the library, but are not declared.
   1340   // Make them available as std::__format::to_chars.
   1341   to_chars_result
   1342   to_chars(char*, char*, __ibm128) noexcept
   1343     __asm("_ZSt8to_charsPcS_e");
   1344 
   1345   to_chars_result
   1346   to_chars(char*, char*, __ibm128, chars_format) noexcept
   1347     __asm("_ZSt8to_charsPcS_eSt12chars_format");
   1348 
   1349   to_chars_result
   1350   to_chars(char*, char*, __ibm128, chars_format, int) noexcept
   1351     __asm("_ZSt8to_charsPcS_eSt12chars_formati");
   1352 #elif __cplusplus == 202002L
   1353   to_chars_result
   1354   to_chars(char*, char*, __ieee128) noexcept
   1355     __asm("_ZSt8to_charsPcS_u9__ieee128");
   1356 
   1357   to_chars_result
   1358   to_chars(char*, char*, __ieee128, chars_format) noexcept
   1359     __asm("_ZSt8to_charsPcS_u9__ieee128St12chars_format");
   1360 
   1361   to_chars_result
   1362   to_chars(char*, char*, __ieee128, chars_format, int) noexcept
   1363     __asm("_ZSt8to_charsPcS_u9__ieee128St12chars_formati");
   1364 #endif
   1365 
   1366 #elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128
   1367 
   1368   // Format 128-bit floating-point types using long double.
   1369   using __float128_t = long double;
   1370 # define _GLIBCXX_FORMAT_F128 1
   1371 
   1372 #elif __FLT128_DIG__ && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
   1373 
   1374   // Format 128-bit floating-point types using _Float128.
   1375   using __float128_t = _Float128;
   1376 # define _GLIBCXX_FORMAT_F128 2
   1377 
   1378 # if __cplusplus == 202002L
   1379   // These overloads exist in the library, but are not declared for C++20.
   1380   // Make them available as std::__format::to_chars.
   1381   to_chars_result
   1382   to_chars(char*, char*, _Float128) noexcept
   1383 #  if _GLIBCXX_INLINE_VERSION
   1384     __asm("_ZNSt3__88to_charsEPcS0_DF128_");
   1385 #  else
   1386     __asm("_ZSt8to_charsPcS_DF128_");
   1387 #  endif
   1388 
   1389   to_chars_result
   1390   to_chars(char*, char*, _Float128, chars_format) noexcept
   1391 #  if _GLIBCXX_INLINE_VERSION
   1392     __asm("_ZNSt3__88to_charsEPcS0_DF128_NS_12chars_formatE");
   1393 #  else
   1394     __asm("_ZSt8to_charsPcS_DF128_St12chars_format");
   1395 #  endif
   1396 
   1397   to_chars_result
   1398   to_chars(char*, char*, _Float128, chars_format, int) noexcept
   1399 #  if _GLIBCXX_INLINE_VERSION
   1400     __asm("_ZNSt3__88to_charsEPcS0_DF128_NS_12chars_formatEi");
   1401 #  else
   1402     __asm("_ZSt8to_charsPcS_DF128_St12chars_formati");
   1403 #  endif
   1404 # endif
   1405 #endif
   1406 
   1407   using std::to_chars;
   1408 
   1409   // We can format a floating-point type iff it is usable with to_chars.
   1410   template<typename _Tp>
   1411     concept __formattable_float
   1412       = is_same_v<remove_cv_t<_Tp>, _Tp> && requires (_Tp __t, char* __p)
   1413       { __format::to_chars(__p, __p, __t, chars_format::scientific, 6); };
   1414 
   1415   template<__char _CharT>
   1416     struct __formatter_fp
   1417     {
   1418       constexpr typename basic_format_parse_context<_CharT>::iterator
   1419       parse(basic_format_parse_context<_CharT>& __pc)
   1420       {
   1421 	_Spec<_CharT> __spec{};
   1422 	const auto __last = __pc.end();
   1423 	auto __first = __pc.begin();
   1424 
   1425 	auto __finalize = [this, &__spec] {
   1426 	  _M_spec = __spec;
   1427 	};
   1428 
   1429 	auto __finished = [&] {
   1430 	  if (__first == __last || *__first == '}')
   1431 	    {
   1432 	      __finalize();
   1433 	      return true;
   1434 	    }
   1435 	  return false;
   1436 	};
   1437 
   1438 	if (__finished())
   1439 	  return __first;
   1440 
   1441 	__first = __spec._M_parse_fill_and_align(__first, __last);
   1442 	if (__finished())
   1443 	  return __first;
   1444 
   1445 	__first = __spec._M_parse_sign(__first, __last);
   1446 	if (__finished())
   1447 	  return __first;
   1448 
   1449 	__first = __spec._M_parse_alternate_form(__first, __last);
   1450 	if (__finished())
   1451 	  return __first;
   1452 
   1453 	__first = __spec._M_parse_zero_fill(__first, __last);
   1454 	if (__finished())
   1455 	  return __first;
   1456 
   1457 	if (__first[0] != '.')
   1458 	  {
   1459 	    __first = __spec._M_parse_width(__first, __last, __pc);
   1460 	    if (__finished())
   1461 	      return __first;
   1462 	  }
   1463 
   1464 	__first = __spec._M_parse_precision(__first, __last, __pc);
   1465 	if (__finished())
   1466 	  return __first;
   1467 
   1468 	__first = __spec._M_parse_locale(__first, __last);
   1469 	if (__finished())
   1470 	  return __first;
   1471 
   1472 	switch (*__first)
   1473 	{
   1474 	  case 'a':
   1475 	    __spec._M_type = _Pres_a;
   1476 	    ++__first;
   1477 	    break;
   1478 	  case 'A':
   1479 	    __spec._M_type = _Pres_A;
   1480 	    ++__first;
   1481 	    break;
   1482 	  case 'e':
   1483 	    __spec._M_type = _Pres_e;
   1484 	    ++__first;
   1485 	    break;
   1486 	  case 'E':
   1487 	    __spec._M_type = _Pres_E;
   1488 	    ++__first;
   1489 	    break;
   1490 	  case 'f':
   1491 	    __spec._M_type = _Pres_f;
   1492 	    ++__first;
   1493 	    break;
   1494 	  case 'F':
   1495 	    __spec._M_type = _Pres_F;
   1496 	    ++__first;
   1497 	    break;
   1498 	  case 'g':
   1499 	    __spec._M_type = _Pres_g;
   1500 	    ++__first;
   1501 	    break;
   1502 	  case 'G':
   1503 	    __spec._M_type = _Pres_G;
   1504 	    ++__first;
   1505 	    break;
   1506 	  }
   1507 
   1508 	if (__finished())
   1509 	  return __first;
   1510 
   1511 	__format::__failed_to_parse_format_spec();
   1512       }
   1513 
   1514       template<typename _Fp, typename _Out>
   1515 	typename basic_format_context<_Out, _CharT>::iterator
   1516 	format(_Fp __v, basic_format_context<_Out, _CharT>& __fc) const
   1517 	{
   1518 	  std::string __dynbuf;
   1519 	  char __buf[128];
   1520 	  to_chars_result __res{};
   1521 
   1522 	  size_t __prec = 6;
   1523 	  bool __use_prec = _M_spec._M_prec_kind != _WP_none;
   1524 	  if (__use_prec)
   1525 	    __prec = _M_spec._M_get_precision(__fc);
   1526 
   1527 	  char* __start = __buf + 1; // reserve space for sign
   1528 	  char* __end = __buf + sizeof(__buf);
   1529 
   1530 	  chars_format __fmt{};
   1531 	  bool __upper = false;
   1532 	  bool __trailing_zeros = false;
   1533 	  char __expc = 'e';
   1534 
   1535 	  switch (_M_spec._M_type)
   1536 	  {
   1537 	    case _Pres_A:
   1538 	      __upper = true;
   1539 	      __expc = 'P';
   1540 	      [[fallthrough]];
   1541 	    case _Pres_a:
   1542 	      if (_M_spec._M_type != _Pres_A)
   1543 		__expc = 'p';
   1544 	      __fmt = chars_format::hex;
   1545 	      break;
   1546 	    case _Pres_E:
   1547 	      __upper = true;
   1548 	      __expc = 'E';
   1549 	      [[fallthrough]];
   1550 	    case _Pres_e:
   1551 	      __use_prec = true;
   1552 	      __fmt = chars_format::scientific;
   1553 	      break;
   1554 	    case _Pres_F:
   1555 	      __upper = true;
   1556 	      [[fallthrough]];
   1557 	    case _Pres_f:
   1558 	      __use_prec = true;
   1559 	      __fmt = chars_format::fixed;
   1560 	      break;
   1561 	    case _Pres_G:
   1562 	      __upper = true;
   1563 	      __expc = 'E';
   1564 	      [[fallthrough]];
   1565 	    case _Pres_g:
   1566 	      __trailing_zeros = true;
   1567 	      __use_prec = true;
   1568 	      __fmt = chars_format::general;
   1569 	      break;
   1570 	    case _Pres_none:
   1571 	      if (__use_prec)
   1572 		__fmt = chars_format::general;
   1573 	      break;
   1574 	    default:
   1575 	      __builtin_unreachable();
   1576 	  }
   1577 
   1578 	  // Write value into buffer using std::to_chars.
   1579 	  auto __to_chars = [&](char* __b, char* __e) {
   1580 	    if (__use_prec)
   1581 	      return __format::to_chars(__b, __e, __v, __fmt, __prec);
   1582 	    else if (__fmt != chars_format{})
   1583 	      return __format::to_chars(__b, __e, __v, __fmt);
   1584 	    else
   1585 	      return __format::to_chars(__b, __e, __v);
   1586 	  };
   1587 
   1588 	  // First try using stack buffer.
   1589 	  __res = __to_chars(__start, __end);
   1590 
   1591 	  if (__builtin_expect(__res.ec == errc::value_too_large, 0))
   1592 	    {
   1593 	      // If the buffer is too small it's probably because of a large
   1594 	      // precision, or a very large value in fixed format.
   1595 	      size_t __guess = 8 + __prec;
   1596 	      if (__fmt == chars_format::fixed) // +ddd.prec
   1597 		{
   1598 		  if constexpr (is_same_v<_Fp, float> || is_same_v<_Fp, double>
   1599 				  || is_same_v<_Fp, long double>)
   1600 		    {
   1601 		      // The number of digits to the left of the decimal point
   1602 		      // is floor(log10(max(abs(__v),1)))+1
   1603 		      int __exp{};
   1604 		      if constexpr (is_same_v<_Fp, float>)
   1605 			__builtin_frexpf(__v, &__exp);
   1606 		      else if constexpr (is_same_v<_Fp, double>)
   1607 			__builtin_frexp(__v, &__exp);
   1608 		      else if constexpr (is_same_v<_Fp, long double>)
   1609 			__builtin_frexpl(__v, &__exp);
   1610 		      if (__exp > 0)
   1611 			__guess += 1U + __exp * 4004U / 13301U; // log10(2) approx.
   1612 		    }
   1613 		  else
   1614 		    __guess += numeric_limits<_Fp>::max_exponent10;
   1615 		}
   1616 	      if (__guess <= sizeof(__buf)) [[unlikely]]
   1617 		__guess = sizeof(__buf) * 2;
   1618 	      __dynbuf.reserve(__guess);
   1619 
   1620 	      do
   1621 		{
   1622 		  auto __overwrite = [&__to_chars, &__res] (char* __p, size_t __n)
   1623 		  {
   1624 		    __res = __to_chars(__p + 1, __p + __n - 1);
   1625 		    return __res.ec == errc{} ? __res.ptr - __p : 0;
   1626 		  };
   1627 
   1628 		  __dynbuf.__resize_and_overwrite(__dynbuf.capacity() * 2,
   1629 						  __overwrite);
   1630 		  __start = __dynbuf.data() + 1; // reserve space for sign
   1631 		  __end = __dynbuf.data() + __dynbuf.size();
   1632 		}
   1633 	      while (__builtin_expect(__res.ec == errc::value_too_large, 0));
   1634 	  }
   1635 
   1636 	  // Use uppercase for 'A', 'E', and 'G' formats.
   1637 	  if (__upper)
   1638 	    {
   1639 	      for (char* __p = __start; __p != __res.ptr; ++__p)
   1640 		*__p = std::toupper(*__p);
   1641 	    }
   1642 
   1643 	  bool __have_sign = true;
   1644 	  // Add sign for non-negative values.
   1645 	  if (!__builtin_signbit(__v))
   1646 	    {
   1647 	      if (_M_spec._M_sign == _Sign_plus)
   1648 		*--__start = '+';
   1649 	      else if (_M_spec._M_sign == _Sign_space)
   1650 		*--__start = ' ';
   1651 	      else
   1652 		__have_sign = false;
   1653 	    }
   1654 
   1655 	  string_view __narrow_str(__start, __res.ptr - __start);
   1656 
   1657 	  // Use alternate form. Ensure decimal point is always present,
   1658 	  // and add trailing zeros (up to precision) for g and G forms.
   1659 	  if (_M_spec._M_alt && __builtin_isfinite(__v))
   1660 	    {
   1661 	      string_view __s = __narrow_str;
   1662 	      size_t __sigfigs; // Number of significant figures.
   1663 	      size_t __z = 0;   // Number of trailing zeros to add.
   1664 	      size_t __p;       // Position of the exponent character (if any).
   1665 	      size_t __d = __s.find('.'); // Position of decimal point.
   1666 	      if (__d != __s.npos) // Found decimal point.
   1667 		{
   1668 		  __p = __s.find(__expc, __d + 1);
   1669 		  if (__p == __s.npos)
   1670 		    __p = __s.size();
   1671 
   1672 		  // If presentation type is g or G we might need to add zeros.
   1673 		  if (__trailing_zeros)
   1674 		    {
   1675 		      // Find number of digits after first significant figure.
   1676 		      if (__s[__have_sign] != '0')
   1677 			// A string like "D.D" or "-D.DDD"
   1678 			__sigfigs = __p - __have_sign - 1;
   1679 		      else
   1680 			// A string like "0.D" or "-0.0DD".
   1681 			// Safe to assume there is a non-zero digit, because
   1682 			// otherwise there would be no decimal point.
   1683 			__sigfigs = __p - __s.find_first_not_of('0', __d + 1);
   1684 		    }
   1685 		}
   1686 	      else // No decimal point, we need to insert one.
   1687 		{
   1688 		  __p = __s.find(__expc); // Find the exponent, if present.
   1689 		  if (__p == __s.npos)
   1690 		    __p = __s.size();
   1691 		  __d = __p; // Position where '.' should be inserted.
   1692 		  __sigfigs = __d - __have_sign;
   1693 		}
   1694 
   1695 	      if (__trailing_zeros && __prec != 0)
   1696 		{
   1697 		  // For g and G presentation types std::to_chars produces
   1698 		  // no more than prec significant figures. Insert this many
   1699 		  // zeros so the result has exactly prec significant figures.
   1700 		  __z = __prec - __sigfigs;
   1701 		}
   1702 
   1703 	      if (size_t __extras = int(__d == __p) + __z) // How many to add.
   1704 		{
   1705 		  if (__dynbuf.empty() && __extras <= size_t(__end - __res.ptr))
   1706 		    {
   1707 		      // The stack buffer is large enough for the result.
   1708 		      // Move exponent to make space for extra chars.
   1709 		      __builtin_memmove(__start + __p + __extras,
   1710 					__start + __p,
   1711 					__s.size() - __p);
   1712 		      if (__d == __p)
   1713 			__start[__p++] = '.';
   1714 		      __builtin_memset(__start + __p, '0', __z);
   1715 		      __narrow_str = {__s.data(), __s.size() + __extras};
   1716 		    }
   1717 		  else // Need to switch to the dynamic buffer.
   1718 		    {
   1719 		      __dynbuf.reserve(__s.size() + __extras);
   1720 		      if (__dynbuf.empty())
   1721 			{
   1722 			  __dynbuf = __s.substr(0, __p);
   1723 			  if (__d == __p)
   1724 			    __dynbuf += '.';
   1725 			  if (__z)
   1726 			    __dynbuf.append(__z, '0');
   1727 			  __dynbuf.append(__s.substr(__p));
   1728 			}
   1729 		      else
   1730 			{
   1731 			  __dynbuf.insert(__p, __extras, '0');
   1732 			  if (__d == __p)
   1733 			    __dynbuf[__p] = '.';
   1734 			}
   1735 		      __narrow_str = __dynbuf;
   1736 		    }
   1737 		}
   1738 	    }
   1739 
   1740 	  basic_string<_CharT> __wstr;
   1741 	  basic_string_view<_CharT> __str;
   1742 	  if constexpr (is_same_v<_CharT, char>)
   1743 	    __str = __narrow_str;
   1744 #ifdef _GLIBCXX_USE_WCHAR_T
   1745 	  else
   1746 	    {
   1747 	      __wstr = std::__to_wstring_numeric(__narrow_str);
   1748 	      __str = __wstr;
   1749 	    }
   1750 #endif
   1751 
   1752 	  if (_M_spec._M_localized && __builtin_isfinite(__v))
   1753 	    {
   1754 	      auto __s = _M_localize(__str, __expc, __fc.locale());
   1755 	      if (!__s.empty())
   1756 		__str = __wstr = std::move(__s);
   1757 	    }
   1758 
   1759 	  size_t __width = _M_spec._M_get_width(__fc);
   1760 
   1761 	  if (__width <= __str.size())
   1762 	    return __format::__write(__fc.out(), __str);
   1763 
   1764 	  char32_t __fill_char = _M_spec._M_fill;
   1765 	  _Align __align = _M_spec._M_align;
   1766 
   1767 	  size_t __nfill = __width - __str.size();
   1768 	  auto __out = __fc.out();
   1769 	  if (__align == _Align_default)
   1770 	    {
   1771 	      __align = _Align_right;
   1772 	      if (_M_spec._M_zero_fill && __builtin_isfinite(__v))
   1773 		{
   1774 		  __fill_char = _CharT('0');
   1775 		  // Write sign before zero filling.
   1776 		  if (!__format::__is_xdigit(__narrow_str[0]))
   1777 		    {
   1778 		      *__out++ = __str[0];
   1779 		      __str.remove_prefix(1);
   1780 		    }
   1781 		}
   1782 	      else
   1783 		__fill_char = _CharT(' ');
   1784 	    }
   1785 	  return __format::__write_padded(std::move(__out), __str,
   1786 					  __align, __nfill, __fill_char);
   1787 	}
   1788 
   1789       // Locale-specific format.
   1790       basic_string<_CharT>
   1791       _M_localize(basic_string_view<_CharT> __str, char __expc,
   1792 		  const locale& __loc) const
   1793       {
   1794 	basic_string<_CharT> __lstr;
   1795 
   1796 	if (__loc == locale::classic())
   1797 	  return __lstr; // Nothing to do.
   1798 
   1799 	const auto& __np = use_facet<numpunct<_CharT>>(__loc);
   1800 	const _CharT __point = __np.decimal_point();
   1801 	const string __grp = __np.grouping();
   1802 
   1803 	_CharT __dot, __exp;
   1804 	if constexpr (is_same_v<_CharT, char>)
   1805 	  {
   1806 	    __dot = '.';
   1807 	    __exp = __expc;
   1808 	  }
   1809 	else
   1810 	  {
   1811 	    __dot = L'.';
   1812 	    switch (__expc)
   1813 	    {
   1814 	      case 'e':
   1815 		__exp = L'e';
   1816 		break;
   1817 	      case 'E':
   1818 		__exp = L'E';
   1819 		break;
   1820 	      case 'p':
   1821 		__exp = L'p';
   1822 		break;
   1823 	      case 'P':
   1824 		__exp = L'P';
   1825 		break;
   1826 	      default:
   1827 		__builtin_unreachable();
   1828 	    }
   1829 	  }
   1830 
   1831 	if (__grp.empty() && __point == __dot)
   1832 	  return __lstr; // Locale uses '.' and no grouping.
   1833 
   1834 	size_t __d = __str.find(__dot);
   1835 	size_t __e = min(__d, __str.find(__exp));
   1836 	if (__e == __str.npos)
   1837 	  __e = __str.size();
   1838 	const size_t __r = __str.size() - __e;
   1839 	auto __overwrite = [&](_CharT* __p, size_t) {
   1840 	  auto __end = std::__add_grouping(__p, __np.thousands_sep(),
   1841 					   __grp.data(), __grp.size(),
   1842 					   __str.data(), __str.data() + __e);
   1843 	  if (__r)
   1844 	    {
   1845 	      if (__d != __str.npos)
   1846 		{
   1847 		  *__end = __point;
   1848 		  ++__end;
   1849 		  ++__e;
   1850 		}
   1851 	      if (__r > 1)
   1852 		__end += __str.copy(__end, __str.npos, __e);
   1853 	    }
   1854 	  return (__end - __p);
   1855 	};
   1856 	__lstr.__resize_and_overwrite(__e * 2 + __r, __overwrite);
   1857 	return __lstr;
   1858       }
   1859 
   1860       _Spec<_CharT> _M_spec{};
   1861     };
   1862 
   1863 } // namespace __format
   1864 /// @endcond
   1865 
   1866   /// Format a character.
   1867   template<__format::__char _CharT>
   1868     struct formatter<_CharT, _CharT>
   1869     {
   1870       formatter() = default;
   1871 
   1872       constexpr typename basic_format_parse_context<_CharT>::iterator
   1873       parse(basic_format_parse_context<_CharT>& __pc)
   1874       {
   1875 	return _M_f.template _M_parse<_CharT>(__pc);
   1876       }
   1877 
   1878       template<typename _Out>
   1879 	typename basic_format_context<_Out, _CharT>::iterator
   1880 	format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const
   1881 	{
   1882 	  if (_M_f._M_spec._M_type == __format::_Pres_none
   1883 	      || _M_f._M_spec._M_type == __format::_Pres_c)
   1884 	    return _M_f._M_format_character(__u, __fc);
   1885 	  else if (_M_f._M_spec._M_type == __format::_Pres_esc)
   1886 	    {
   1887 	      // TODO
   1888 	      return __fc.out();
   1889 	    }
   1890 	  else
   1891 	    return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u), __fc);
   1892 	}
   1893 
   1894 #if __cpp_lib_format_ranges
   1895       constexpr void
   1896       set_debug_format() noexcept
   1897       { _M_f._M_spec._M_type = __format::_Pres_esc; }
   1898 #endif
   1899 
   1900     private:
   1901       __format::__formatter_int<_CharT> _M_f;
   1902     };
   1903 
   1904 #ifdef _GLIBCXX_USE_WCHAR_T
   1905   /// Format a char value for wide character output.
   1906   template<>
   1907     struct formatter<char, wchar_t>
   1908     {
   1909       formatter() = default;
   1910 
   1911       constexpr typename basic_format_parse_context<wchar_t>::iterator
   1912       parse(basic_format_parse_context<wchar_t>& __pc)
   1913       {
   1914 	return _M_f._M_parse<char>(__pc);
   1915       }
   1916 
   1917       template<typename _Out>
   1918 	typename basic_format_context<_Out, wchar_t>::iterator
   1919 	format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
   1920 	{
   1921 	  if (_M_f._M_spec._M_type == __format::_Pres_none
   1922 	      || _M_f._M_spec._M_type == __format::_Pres_c)
   1923 	    return _M_f._M_format_character(__u, __fc);
   1924 	  else if (_M_f._M_spec._M_type == __format::_Pres_esc)
   1925 	    {
   1926 	      // TODO
   1927 	      return __fc.out();
   1928 	    }
   1929 	  else
   1930 	    return _M_f.format(static_cast<unsigned char>(__u), __fc);
   1931 	}
   1932 
   1933 #if __cpp_lib_format_ranges
   1934       constexpr void
   1935       set_debug_format() noexcept
   1936       { _M_f._M_spec._M_type = __format::_Pres_esc; }
   1937 #endif
   1938 
   1939     private:
   1940       __format::__formatter_int<wchar_t> _M_f;
   1941     };
   1942 #endif // USE_WCHAR_T
   1943 
   1944   /** Format a string.
   1945    * @{
   1946    */
   1947   template<__format::__char _CharT>
   1948     struct formatter<_CharT*, _CharT>
   1949     {
   1950       formatter() = default;
   1951 
   1952       [[__gnu__::__always_inline__]]
   1953       constexpr typename basic_format_parse_context<_CharT>::iterator
   1954       parse(basic_format_parse_context<_CharT>& __pc)
   1955       { return _M_f.parse(__pc); }
   1956 
   1957       template<typename _Out>
   1958 	[[__gnu__::__nonnull__]]
   1959 	typename basic_format_context<_Out, _CharT>::iterator
   1960 	format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc) const
   1961 	{ return _M_f.format(__u, __fc); }
   1962 
   1963 #if __cpp_lib_format_ranges
   1964       constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
   1965 #endif
   1966 
   1967     private:
   1968       __format::__formatter_str<_CharT> _M_f;
   1969     };
   1970 
   1971   template<__format::__char _CharT>
   1972     struct formatter<const _CharT*, _CharT>
   1973     {
   1974       formatter() = default;
   1975 
   1976       [[__gnu__::__always_inline__]]
   1977       constexpr typename basic_format_parse_context<_CharT>::iterator
   1978       parse(basic_format_parse_context<_CharT>& __pc)
   1979       { return _M_f.parse(__pc); }
   1980 
   1981       template<typename _Out>
   1982 	[[__gnu__::__nonnull__]]
   1983 	typename basic_format_context<_Out, _CharT>::iterator
   1984 	format(const _CharT* __u,
   1985 	       basic_format_context<_Out, _CharT>& __fc) const
   1986 	{ return _M_f.format(__u, __fc); }
   1987 
   1988 #if __cpp_lib_format_ranges
   1989       constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
   1990 #endif
   1991 
   1992     private:
   1993       __format::__formatter_str<_CharT> _M_f;
   1994     };
   1995 
   1996   template<__format::__char _CharT, size_t _Nm>
   1997     struct formatter<_CharT[_Nm], _CharT>
   1998     {
   1999       formatter() = default;
   2000 
   2001       [[__gnu__::__always_inline__]]
   2002       constexpr typename basic_format_parse_context<_CharT>::iterator
   2003       parse(basic_format_parse_context<_CharT>& __pc)
   2004       { return _M_f.parse(__pc); }
   2005 
   2006       template<typename _Out>
   2007 	typename basic_format_context<_Out, _CharT>::iterator
   2008 	format(const _CharT (&__u)[_Nm],
   2009 	       basic_format_context<_Out, _CharT>& __fc) const
   2010 	{ return _M_f.format({__u, _Nm}, __fc); }
   2011 
   2012 #if __cpp_lib_format_ranges
   2013       constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
   2014 #endif
   2015 
   2016     private:
   2017       __format::__formatter_str<_CharT> _M_f;
   2018     };
   2019 
   2020   template<typename _Traits, typename _Alloc>
   2021     struct formatter<basic_string<char, _Traits, _Alloc>, char>
   2022     {
   2023       formatter() = default;
   2024 
   2025       [[__gnu__::__always_inline__]]
   2026       constexpr typename basic_format_parse_context<char>::iterator
   2027       parse(basic_format_parse_context<char>& __pc)
   2028       { return _M_f.parse(__pc); }
   2029 
   2030       template<typename _Out>
   2031 	typename basic_format_context<_Out, char>::iterator
   2032 	format(const basic_string<char, _Traits, _Alloc>& __u,
   2033 	       basic_format_context<_Out, char>& __fc) const
   2034 	{ return _M_f.format(__u, __fc); }
   2035 
   2036 #if __cpp_lib_format_ranges
   2037       constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
   2038 #endif
   2039 
   2040     private:
   2041       __format::__formatter_str<char> _M_f;
   2042     };
   2043 
   2044 #ifdef _GLIBCXX_USE_WCHAR_T
   2045   template<typename _Traits, typename _Alloc>
   2046     struct formatter<basic_string<wchar_t, _Traits, _Alloc>, wchar_t>
   2047     {
   2048       formatter() = default;
   2049 
   2050       [[__gnu__::__always_inline__]]
   2051       constexpr typename basic_format_parse_context<wchar_t>::iterator
   2052       parse(basic_format_parse_context<wchar_t>& __pc)
   2053       { return _M_f.parse(__pc); }
   2054 
   2055       template<typename _Out>
   2056 	typename basic_format_context<_Out, wchar_t>::iterator
   2057 	format(const basic_string<wchar_t, _Traits, _Alloc>& __u,
   2058 	       basic_format_context<_Out, wchar_t>& __fc) const
   2059 	{ return _M_f.format(__u, __fc); }
   2060 
   2061 #if __cpp_lib_format_ranges
   2062       constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
   2063 #endif
   2064 
   2065     private:
   2066       __format::__formatter_str<wchar_t> _M_f;
   2067     };
   2068 #endif // USE_WCHAR_T
   2069 
   2070   template<typename _Traits>
   2071     struct formatter<basic_string_view<char, _Traits>, char>
   2072     {
   2073       formatter() = default;
   2074 
   2075       [[__gnu__::__always_inline__]]
   2076       constexpr typename basic_format_parse_context<char>::iterator
   2077       parse(basic_format_parse_context<char>& __pc)
   2078       { return _M_f.parse(__pc); }
   2079 
   2080       template<typename _Out>
   2081 	typename basic_format_context<_Out, char>::iterator
   2082 	format(basic_string_view<char, _Traits> __u,
   2083 	       basic_format_context<_Out, char>& __fc) const
   2084 	{ return _M_f.format(__u, __fc); }
   2085 
   2086 #if __cpp_lib_format_ranges
   2087       constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
   2088 #endif
   2089 
   2090     private:
   2091       __format::__formatter_str<char> _M_f;
   2092     };
   2093 
   2094 #ifdef _GLIBCXX_USE_WCHAR_T
   2095   template<typename _Traits>
   2096     struct formatter<basic_string_view<wchar_t, _Traits>, wchar_t>
   2097     {
   2098       formatter() = default;
   2099 
   2100       [[__gnu__::__always_inline__]]
   2101       constexpr typename basic_format_parse_context<wchar_t>::iterator
   2102       parse(basic_format_parse_context<wchar_t>& __pc)
   2103       { return _M_f.parse(__pc); }
   2104 
   2105       template<typename _Out>
   2106 	typename basic_format_context<_Out, wchar_t>::iterator
   2107 	format(basic_string_view<wchar_t, _Traits> __u,
   2108 	       basic_format_context<_Out, wchar_t>& __fc) const
   2109 	{ return _M_f.format(__u, __fc); }
   2110 
   2111 #if __cpp_lib_format_ranges
   2112       constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
   2113 #endif
   2114 
   2115     private:
   2116       __format::__formatter_str<wchar_t> _M_f;
   2117     };
   2118 #endif // USE_WCHAR_T
   2119   /// @}
   2120 
   2121 /// @cond undocumented
   2122 namespace __format
   2123 {
   2124   // each cv-unqualified arithmetic type ArithmeticT other than
   2125   // char, wchar_t, char8_t, char16_t, or char32_t
   2126   template<typename _Tp>
   2127     constexpr bool __is_formattable_integer = __is_integer<_Tp>::__value;
   2128 
   2129 #if defined __SIZEOF_INT128__
   2130   template<> inline constexpr bool __is_formattable_integer<__int128>  = true;
   2131   template<> inline constexpr bool __is_formattable_integer<unsigned __int128>
   2132       = true;
   2133 #endif
   2134 
   2135   template<> inline constexpr bool __is_formattable_integer<char> = false;
   2136   template<> inline constexpr bool __is_formattable_integer<wchar_t> = false;
   2137 #ifdef _GLIBCXX_USE_CHAR8_T
   2138   template<> inline constexpr bool __is_formattable_integer<char8_t> = false;
   2139 #endif
   2140   template<> inline constexpr bool __is_formattable_integer<char16_t> = false;
   2141   template<> inline constexpr bool __is_formattable_integer<char32_t> = false;
   2142 }
   2143 /// @endcond
   2144 
   2145   /// Format an integer.
   2146   template<typename _Tp, __format::__char _CharT>
   2147     requires __format::__is_formattable_integer<_Tp>
   2148     struct formatter<_Tp, _CharT>
   2149     {
   2150       formatter() = default;
   2151 
   2152       [[__gnu__::__always_inline__]]
   2153       constexpr typename basic_format_parse_context<_CharT>::iterator
   2154       parse(basic_format_parse_context<_CharT>& __pc)
   2155       {
   2156 	return _M_f.template _M_parse<_Tp>(__pc);
   2157       }
   2158 
   2159       template<typename _Out>
   2160 	typename basic_format_context<_Out, _CharT>::iterator
   2161 	format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
   2162 	{ return _M_f.format(__u, __fc); }
   2163 
   2164     private:
   2165       __format::__formatter_int<_CharT> _M_f;
   2166     };
   2167 
   2168 #if defined __glibcxx_to_chars
   2169   /// Format a floating-point value.
   2170   template<__format::__formattable_float _Tp, __format::__char _CharT>
   2171     struct formatter<_Tp, _CharT>
   2172     {
   2173       formatter() = default;
   2174 
   2175       [[__gnu__::__always_inline__]]
   2176       constexpr typename basic_format_parse_context<_CharT>::iterator
   2177       parse(basic_format_parse_context<_CharT>& __pc)
   2178       { return _M_f.parse(__pc); }
   2179 
   2180       template<typename _Out>
   2181 	typename basic_format_context<_Out, _CharT>::iterator
   2182 	format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
   2183 	{ return _M_f.format(__u, __fc); }
   2184 
   2185     private:
   2186       __format::__formatter_fp<_CharT> _M_f;
   2187     };
   2188 
   2189 #if __LDBL_MANT_DIG__ == __DBL_MANT_DIG__
   2190   // Reuse __formatter_fp<C>::format<double, Out> for long double.
   2191   template<__format::__char _CharT>
   2192     struct formatter<long double, _CharT>
   2193     {
   2194       formatter() = default;
   2195 
   2196       [[__gnu__::__always_inline__]]
   2197       constexpr typename basic_format_parse_context<_CharT>::iterator
   2198       parse(basic_format_parse_context<_CharT>& __pc)
   2199       { return _M_f.parse(__pc); }
   2200 
   2201       template<typename _Out>
   2202 	typename basic_format_context<_Out, _CharT>::iterator
   2203 	format(long double __u, basic_format_context<_Out, _CharT>& __fc) const
   2204 	{ return _M_f.format((double)__u, __fc); }
   2205 
   2206     private:
   2207       __format::__formatter_fp<_CharT> _M_f;
   2208     };
   2209 #endif
   2210 
   2211 #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   2212   // Reuse __formatter_fp<C>::format<float, Out> for _Float16.
   2213   template<__format::__char _CharT>
   2214     struct formatter<_Float16, _CharT>
   2215     {
   2216       formatter() = default;
   2217 
   2218       [[__gnu__::__always_inline__]]
   2219       constexpr typename basic_format_parse_context<_CharT>::iterator
   2220       parse(basic_format_parse_context<_CharT>& __pc)
   2221       { return _M_f.parse(__pc); }
   2222 
   2223       template<typename _Out>
   2224 	typename basic_format_context<_Out, _CharT>::iterator
   2225 	format(_Float16 __u, basic_format_context<_Out, _CharT>& __fc) const
   2226 	{ return _M_f.format((float)__u, __fc); }
   2227 
   2228     private:
   2229       __format::__formatter_fp<_CharT> _M_f;
   2230     };
   2231 #endif
   2232 
   2233 #if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   2234   // Reuse __formatter_fp<C>::format<float, Out> for _Float32.
   2235   template<__format::__char _CharT>
   2236     struct formatter<_Float32, _CharT>
   2237     {
   2238       formatter() = default;
   2239 
   2240       [[__gnu__::__always_inline__]]
   2241       constexpr typename basic_format_parse_context<_CharT>::iterator
   2242       parse(basic_format_parse_context<_CharT>& __pc)
   2243       { return _M_f.parse(__pc); }
   2244 
   2245       template<typename _Out>
   2246 	typename basic_format_context<_Out, _CharT>::iterator
   2247 	format(_Float32 __u, basic_format_context<_Out, _CharT>& __fc) const
   2248 	{ return _M_f.format((float)__u, __fc); }
   2249 
   2250     private:
   2251       __format::__formatter_fp<_CharT> _M_f;
   2252     };
   2253 #endif
   2254 
   2255 #if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
   2256   // Reuse __formatter_fp<C>::format<double, Out> for _Float64.
   2257   template<__format::__char _CharT>
   2258     struct formatter<_Float64, _CharT>
   2259     {
   2260       formatter() = default;
   2261 
   2262       [[__gnu__::__always_inline__]]
   2263       constexpr typename basic_format_parse_context<_CharT>::iterator
   2264       parse(basic_format_parse_context<_CharT>& __pc)
   2265       { return _M_f.parse(__pc); }
   2266 
   2267       template<typename _Out>
   2268 	typename basic_format_context<_Out, _CharT>::iterator
   2269 	format(_Float64 __u, basic_format_context<_Out, _CharT>& __fc) const
   2270 	{ return _M_f.format((double)__u, __fc); }
   2271 
   2272     private:
   2273       __format::__formatter_fp<_CharT> _M_f;
   2274     };
   2275 #endif
   2276 
   2277 #if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128 == 1
   2278   // Reuse __formatter_fp<C>::format<__float128_t, Out> for _Float128.
   2279   template<__format::__char _CharT>
   2280     struct formatter<_Float128, _CharT>
   2281     {
   2282       formatter() = default;
   2283 
   2284       [[__gnu__::__always_inline__]]
   2285       constexpr typename basic_format_parse_context<_CharT>::iterator
   2286       parse(basic_format_parse_context<_CharT>& __pc)
   2287       { return _M_f.parse(__pc); }
   2288 
   2289       template<typename _Out>
   2290 	typename basic_format_context<_Out, _CharT>::iterator
   2291 	format(_Float128 __u, basic_format_context<_Out, _CharT>& __fc) const
   2292 	{ return _M_f.format((__format::__float128_t)__u, __fc); }
   2293 
   2294     private:
   2295       __format::__formatter_fp<_CharT> _M_f;
   2296     };
   2297 #endif
   2298 
   2299 #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   2300   // Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t.
   2301   template<__format::__char _CharT>
   2302     struct formatter<__gnu_cxx::__bfloat16_t, _CharT>
   2303     {
   2304       formatter() = default;
   2305 
   2306       [[__gnu__::__always_inline__]]
   2307       constexpr typename basic_format_parse_context<_CharT>::iterator
   2308       parse(basic_format_parse_context<_CharT>& __pc)
   2309       { return _M_f.parse(__pc); }
   2310 
   2311       template<typename _Out>
   2312 	typename basic_format_context<_Out, _CharT>::iterator
   2313 	format(__gnu_cxx::__bfloat16_t __u,
   2314 	       basic_format_context<_Out, _CharT>& __fc) const
   2315 	{ return _M_f.format((float)__u, __fc); }
   2316 
   2317     private:
   2318       __format::__formatter_fp<_CharT> _M_f;
   2319     };
   2320 #endif
   2321 #endif // __cpp_lib_to_chars
   2322 
   2323   /** Format a pointer.
   2324    * @{
   2325    */
   2326   template<__format::__char _CharT>
   2327     struct formatter<const void*, _CharT>
   2328     {
   2329       formatter() = default;
   2330 
   2331       constexpr typename basic_format_parse_context<_CharT>::iterator
   2332       parse(basic_format_parse_context<_CharT>& __pc)
   2333       {
   2334 	__format::_Spec<_CharT> __spec{};
   2335 	const auto __last = __pc.end();
   2336 	auto __first = __pc.begin();
   2337 
   2338 	auto __finalize = [this, &__spec] {
   2339 	  _M_spec = __spec;
   2340 	};
   2341 
   2342 	auto __finished = [&] {
   2343 	  if (__first == __last || *__first == '}')
   2344 	    {
   2345 	      __finalize();
   2346 	      return true;
   2347 	    }
   2348 	  return false;
   2349 	};
   2350 
   2351 	if (__finished())
   2352 	  return __first;
   2353 
   2354 	__first = __spec._M_parse_fill_and_align(__first, __last);
   2355 	if (__finished())
   2356 	  return __first;
   2357 
   2358 // _GLIBCXX_RESOLVE_LIB_DEFECTS
   2359 // P2510R3 Formatting pointers
   2360 #if __cplusplus > 202302L || ! defined __STRICT_ANSI__
   2361 #define _GLIBCXX_P2518R3 1
   2362 #else
   2363 #define _GLIBCXX_P2518R3 0
   2364 #endif
   2365 
   2366 #if _GLIBCXX_P2518R3
   2367 	__first = __spec._M_parse_zero_fill(__first, __last);
   2368 	if (__finished())
   2369 	  return __first;
   2370 #endif
   2371 
   2372 	__first = __spec._M_parse_width(__first, __last, __pc);
   2373 
   2374 	if (__first != __last)
   2375 	  {
   2376 	    if (*__first == 'p')
   2377 	      ++__first;
   2378 #if _GLIBCXX_P2518R3
   2379 	    else if (*__first == 'P')
   2380 	    {
   2381 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
   2382 	      // P2510R3 Formatting pointers
   2383 	      __spec._M_type = __format::_Pres_P;
   2384 	      ++__first;
   2385 	    }
   2386 #endif
   2387 	  }
   2388 
   2389 	if (__finished())
   2390 	  return __first;
   2391 
   2392 	__format::__failed_to_parse_format_spec();
   2393       }
   2394 
   2395       template<typename _Out>
   2396 	typename basic_format_context<_Out, _CharT>::iterator
   2397 	format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const
   2398 	{
   2399 	  auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v);
   2400 	  char __buf[2 + sizeof(__v) * 2];
   2401 	  auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf),
   2402 					     __u, 16);
   2403 	  int __n = __ptr - __buf;
   2404 	  __buf[0] = '0';
   2405 	  __buf[1] = 'x';
   2406 #if _GLIBCXX_P2518R3
   2407 	  if (_M_spec._M_type == __format::_Pres_P)
   2408 	    {
   2409 	      __buf[1] = 'X';
   2410 	      for (auto __p = __buf + 2; __p != __ptr; ++__p)
   2411 #if __has_builtin(__builtin_toupper)
   2412 		*__p = __builtin_toupper(*__p);
   2413 #else
   2414 		*__p = std::toupper(*__p);
   2415 #endif
   2416 	    }
   2417 #endif
   2418 
   2419 	  basic_string_view<_CharT> __str;
   2420 	  if constexpr (is_same_v<_CharT, char>)
   2421 	    __str = string_view(__buf, __n);
   2422 #ifdef _GLIBCXX_USE_WCHAR_T
   2423 	  else
   2424 	    {
   2425 	      auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
   2426 	      std::__to_wstring_numeric(__buf, __n, __p);
   2427 	      __str = wstring_view(__p, __n);
   2428 	    }
   2429 #endif
   2430 
   2431 #if _GLIBCXX_P2518R3
   2432 	  if (_M_spec._M_zero_fill)
   2433 	    {
   2434 	      size_t __width = _M_spec._M_get_width(__fc);
   2435 	      if (__width <= __str.size())
   2436 		return __format::__write(__fc.out(), __str);
   2437 
   2438 	      auto __out = __fc.out();
   2439 	      // Write "0x" or "0X" prefix before zero-filling.
   2440 	      __out = __format::__write(std::move(__out), __str.substr(0, 2));
   2441 	      __str.remove_prefix(2);
   2442 	      size_t __nfill = __width - __n;
   2443 	      return __format::__write_padded(std::move(__out), __str,
   2444 					      __format::_Align_right,
   2445 					      __nfill, _CharT('0'));
   2446 	    }
   2447 #endif
   2448 
   2449 	  return __format::__write_padded_as_spec(__str, __n, __fc, _M_spec,
   2450 						  __format::_Align_right);
   2451 	}
   2452 
   2453     private:
   2454       __format::_Spec<_CharT> _M_spec{};
   2455     };
   2456 
   2457   template<__format::__char _CharT>
   2458     struct formatter<void*, _CharT>
   2459     {
   2460       formatter() = default;
   2461 
   2462       [[__gnu__::__always_inline__]]
   2463       constexpr typename basic_format_parse_context<_CharT>::iterator
   2464       parse(basic_format_parse_context<_CharT>& __pc)
   2465       { return _M_f.parse(__pc); }
   2466 
   2467       template<typename _Out>
   2468 	typename basic_format_context<_Out, _CharT>::iterator
   2469 	format(void* __v, basic_format_context<_Out, _CharT>& __fc) const
   2470 	{ return _M_f.format(__v, __fc); }
   2471 
   2472     private:
   2473       formatter<const void*, _CharT> _M_f;
   2474     };
   2475 
   2476   template<__format::__char _CharT>
   2477     struct formatter<nullptr_t, _CharT>
   2478     {
   2479       formatter() = default;
   2480 
   2481       [[__gnu__::__always_inline__]]
   2482       constexpr typename basic_format_parse_context<_CharT>::iterator
   2483       parse(basic_format_parse_context<_CharT>& __pc)
   2484       { return _M_f.parse(__pc); }
   2485 
   2486       template<typename _Out>
   2487 	typename basic_format_context<_Out, _CharT>::iterator
   2488 	format(nullptr_t, basic_format_context<_Out, _CharT>& __fc) const
   2489 	{ return _M_f.format(nullptr, __fc); }
   2490 
   2491     private:
   2492       formatter<const void*, _CharT> _M_f;
   2493     };
   2494   /// @}
   2495 
   2496 #if defined _GLIBCXX_USE_WCHAR_T && __cpp_lib_format_ranges
   2497   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   2498   // 3944. Formatters converting sequences of char to sequences of wchar_t
   2499 
   2500   namespace __format { struct __disabled; }
   2501 
   2502   // std::formatter<__disabled, C> uses the primary template, which is disabled.
   2503   template<>
   2504     struct formatter<char*, wchar_t>
   2505     : private formatter<__format::__disabled, wchar_t> { };
   2506   template<>
   2507     struct formatter<const char*, wchar_t>
   2508     : private formatter<__format::__disabled, wchar_t> { };
   2509   template<size_t _Nm>
   2510     struct formatter<char[_Nm], wchar_t>
   2511     : private formatter<__format::__disabled, wchar_t> { };
   2512   template<class _Traits, class _Allocator>
   2513     struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t>
   2514     : private formatter<__format::__disabled, wchar_t> { };
   2515   template<class _Traits>
   2516     struct formatter<basic_string_view<char, _Traits>, wchar_t>
   2517     : private formatter<__format::__disabled, wchar_t> { };
   2518 #endif
   2519 
   2520 /// @cond undocumented
   2521 namespace __format
   2522 {
   2523   template<typename _Tp, typename _Context,
   2524 	   typename _Formatter
   2525 	     = typename _Context::template formatter_type<remove_const_t<_Tp>>,
   2526 	   typename _ParseContext
   2527 	     = basic_format_parse_context<typename _Context::char_type>>
   2528     concept __parsable_with
   2529       = semiregular<_Formatter>
   2530 	  && requires (_Formatter __f, _ParseContext __pc)
   2531     {
   2532       { __f.parse(__pc) } -> same_as<typename _ParseContext::iterator>;
   2533     };
   2534 
   2535   template<typename _Tp, typename _Context,
   2536 	   typename _Formatter
   2537 	     = typename _Context::template formatter_type<remove_const_t<_Tp>>,
   2538 	   typename _ParseContext
   2539 	     = basic_format_parse_context<typename _Context::char_type>>
   2540     concept __formattable_with
   2541       = semiregular<_Formatter>
   2542 	  && requires (const _Formatter __cf, _Tp&& __t, _Context __fc)
   2543     {
   2544       { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>;
   2545     };
   2546 
   2547   // An unspecified output iterator type used in the `formattable` concept.
   2548   template<typename _CharT>
   2549     using _Iter_for = back_insert_iterator<basic_string<_CharT>>;
   2550 
   2551   template<typename _Tp, typename _CharT,
   2552 	   typename _Context = basic_format_context<_Iter_for<_CharT>, _CharT>>
   2553     concept __formattable_impl
   2554       = __parsable_with<_Tp, _Context> && __formattable_with<_Tp, _Context>;
   2555 
   2556 } // namespace __format
   2557 /// @endcond
   2558 
   2559 // Concept std::formattable was introduced by P2286R8 "Formatting Ranges",
   2560 // but we can't guard it with __cpp_lib_format_ranges until we define that!
   2561 #if __cplusplus > 202002L
   2562   // [format.formattable], concept formattable
   2563   template<typename _Tp, typename _CharT>
   2564     concept formattable
   2565       = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>;
   2566 #endif
   2567 
   2568 #if __cpp_lib_format_ranges
   2569   /// @cond undocumented
   2570 namespace __format
   2571 {
   2572   template<typename _Rg, typename _CharT>
   2573     concept __const_formattable_range
   2574       = ranges::input_range<const _Rg>
   2575 	  && formattable<ranges::range_reference_t<const _Rg>, _CharT>;
   2576 
   2577   template<typename _Rg, typename _CharT>
   2578     using __maybe_const_range
   2579       = conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>;
   2580 } // namespace __format
   2581   /// @endcond
   2582 #endif // format_ranges
   2583 
   2584   /// An iterator after the last character written, and the number of
   2585   /// characters that would have been written.
   2586   template<typename _Out>
   2587     struct format_to_n_result
   2588     {
   2589       _Out out;
   2590       iter_difference_t<_Out> size;
   2591     };
   2592 
   2593 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   2594 template<typename, typename> class vector;
   2595 _GLIBCXX_END_NAMESPACE_CONTAINER
   2596 
   2597 /// @cond undocumented
   2598 namespace __format
   2599 {
   2600   template<typename _CharT>
   2601     class _Sink_iter
   2602     {
   2603       _Sink<_CharT>* _M_sink = nullptr;
   2604 
   2605     public:
   2606       using iterator_category = output_iterator_tag;
   2607       using value_type = void;
   2608       using difference_type = ptrdiff_t;
   2609       using pointer = void;
   2610       using reference = void;
   2611 
   2612       _Sink_iter() = default;
   2613       _Sink_iter(const _Sink_iter&) = default;
   2614       _Sink_iter& operator=(const _Sink_iter&) = default;
   2615 
   2616       [[__gnu__::__always_inline__]]
   2617       explicit constexpr
   2618       _Sink_iter(_Sink<_CharT>& __sink) : _M_sink(std::addressof(__sink)) { }
   2619 
   2620       [[__gnu__::__always_inline__]]
   2621       constexpr _Sink_iter&
   2622       operator=(_CharT __c)
   2623       {
   2624 	_M_sink->_M_write(__c);
   2625 	return *this;
   2626       }
   2627 
   2628       [[__gnu__::__always_inline__]]
   2629       constexpr _Sink_iter&
   2630       operator=(basic_string_view<_CharT> __s)
   2631       {
   2632 	_M_sink->_M_write(__s);
   2633 	return *this;
   2634       }
   2635 
   2636       [[__gnu__::__always_inline__]]
   2637       constexpr _Sink_iter&
   2638       operator*() { return *this; }
   2639 
   2640       [[__gnu__::__always_inline__]]
   2641       constexpr _Sink_iter&
   2642       operator++() { return *this; }
   2643 
   2644       [[__gnu__::__always_inline__]]
   2645       constexpr _Sink_iter
   2646       operator++(int) { return *this; }
   2647 
   2648       auto
   2649       _M_reserve(size_t __n) const
   2650       { return _M_sink->_M_reserve(__n); }
   2651     };
   2652 
   2653   // Abstract base class for type-erased character sinks.
   2654   // All formatting and output is done via this type's iterator,
   2655   // to reduce the number of different template instantiations.
   2656   template<typename _CharT>
   2657     class _Sink
   2658     {
   2659       friend class _Sink_iter<_CharT>;
   2660 
   2661       span<_CharT> _M_span;
   2662       typename span<_CharT>::iterator _M_next;
   2663 
   2664       // Called when the span is full, to make more space available.
   2665       // Precondition: _M_next != _M_span.begin()
   2666       // Postcondition: _M_next != _M_span.end()
   2667       // TODO: remove the precondition? could make overflow handle it.
   2668       virtual void _M_overflow() = 0;
   2669 
   2670     protected:
   2671       // Precondition: __span.size() != 0
   2672       [[__gnu__::__always_inline__]]
   2673       explicit constexpr
   2674       _Sink(span<_CharT> __span) noexcept
   2675       : _M_span(__span), _M_next(__span.begin())
   2676       { }
   2677 
   2678       // The portion of the span that has been written to.
   2679       [[__gnu__::__always_inline__]]
   2680       span<_CharT>
   2681       _M_used() const noexcept
   2682       { return _M_span.first(_M_next - _M_span.begin()); }
   2683 
   2684       // The portion of the span that has not been written to.
   2685       [[__gnu__::__always_inline__]]
   2686       constexpr span<_CharT>
   2687       _M_unused() const noexcept
   2688       { return _M_span.subspan(_M_next - _M_span.begin()); }
   2689 
   2690       // Use the start of the span as the next write position.
   2691       [[__gnu__::__always_inline__]]
   2692       constexpr void
   2693       _M_rewind() noexcept
   2694       { _M_next = _M_span.begin(); }
   2695 
   2696       // Replace the current output range.
   2697       void
   2698       _M_reset(span<_CharT> __s, size_t __pos = 0) noexcept
   2699       {
   2700 	_M_span = __s;
   2701 	_M_next = __s.begin() + __pos;
   2702       }
   2703 
   2704       // Called by the iterator for *it++ = c
   2705       constexpr void
   2706       _M_write(_CharT __c)
   2707       {
   2708 	*_M_next++ = __c;
   2709 	if (_M_next - _M_span.begin() == std::ssize(_M_span)) [[unlikely]]
   2710 	  _M_overflow();
   2711       }
   2712 
   2713       constexpr void
   2714       _M_write(basic_string_view<_CharT> __s)
   2715       {
   2716 	span __to = _M_unused();
   2717 	while (__to.size() <= __s.size())
   2718 	  {
   2719 	    __s.copy(__to.data(), __to.size());
   2720 	    _M_next += __to.size();
   2721 	    __s.remove_prefix(__to.size());
   2722 	    _M_overflow();
   2723 	    __to = _M_unused();
   2724 	  }
   2725 	if (__s.size())
   2726 	  {
   2727 	    __s.copy(__to.data(), __s.size());
   2728 	    _M_next += __s.size();
   2729 	  }
   2730       }
   2731 
   2732       // A successful _Reservation can be used to directly write
   2733       // up to N characters to the sink to avoid unwanted buffering.
   2734       struct _Reservation
   2735       {
   2736 	// True if the reservation was successful, false otherwise.
   2737 	explicit operator bool() const noexcept { return _M_sink; }
   2738 	// A pointer to write directly to the sink.
   2739 	_CharT* get() const noexcept { return _M_sink->_M_next.operator->(); }
   2740 	// Add n to the _M_next iterator for the sink.
   2741 	void _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
   2742 	_Sink* _M_sink;
   2743       };
   2744 
   2745       // Attempt to reserve space to write n characters to the sink.
   2746       // If anything is written to the reservation then there must be a call
   2747       // to _M_bump(N2) before any call to another member function of *this,
   2748       // where N2 is the number of characters written.
   2749       virtual _Reservation
   2750       _M_reserve(size_t __n)
   2751       {
   2752 	if (__n <= _M_unused().size())
   2753 	  return { this };
   2754 
   2755 	if (__n <= _M_span.size()) // Cannot meet the request.
   2756 	  {
   2757 	    _M_overflow(); // Make more space available.
   2758 	    if (__n <= _M_unused().size())
   2759 	      return { this };
   2760 	  }
   2761 	return { nullptr };
   2762       }
   2763 
   2764       // Update the next output position after writing directly to the sink.
   2765       // pre: no calls to _M_write or _M_overflow since _M_reserve.
   2766       virtual void
   2767       _M_bump(size_t __n)
   2768       { _M_next += __n; }
   2769 
   2770     public:
   2771       _Sink(const _Sink&) = delete;
   2772       _Sink& operator=(const _Sink&) = delete;
   2773 
   2774       [[__gnu__::__always_inline__]]
   2775       constexpr _Sink_iter<_CharT>
   2776       out() noexcept
   2777       { return _Sink_iter<_CharT>(*this); }
   2778     };
   2779 
   2780   // A sink with an internal buffer. This is used to implement concrete sinks.
   2781   template<typename _CharT>
   2782     class _Buf_sink : public _Sink<_CharT>
   2783     {
   2784     protected:
   2785       _CharT _M_buf[32 * sizeof(void*) / sizeof(_CharT)];
   2786 
   2787       [[__gnu__::__always_inline__]]
   2788       constexpr
   2789       _Buf_sink() noexcept
   2790       : _Sink<_CharT>(_M_buf)
   2791       { }
   2792     };
   2793 
   2794   using _GLIBCXX_STD_C::vector;
   2795 
   2796   // A sink that fills a sequence (e.g. std::string, std::vector, std::deque).
   2797   // Writes to a buffer then appends that to the sequence when it fills up.
   2798   template<typename _Seq>
   2799     class _Seq_sink final : public _Buf_sink<typename _Seq::value_type>
   2800     {
   2801       using _CharT = typename _Seq::value_type;
   2802 
   2803       _Seq _M_seq;
   2804 
   2805       // Transfer buffer contents to the sequence, so buffer can be refilled.
   2806       void
   2807       _M_overflow() override
   2808       {
   2809 	auto __s = this->_M_used();
   2810 	if (__s.empty()) [[unlikely]]
   2811 	  return; // Nothing in the buffer to transfer to _M_seq.
   2812 
   2813 	// If _M_reserve was called then _M_bump must have been called too.
   2814 	_GLIBCXX_DEBUG_ASSERT(__s.data() != _M_seq.data());
   2815 
   2816 	if constexpr (__is_specialization_of<_Seq, basic_string>)
   2817 	  _M_seq.append(__s.data(), __s.size());
   2818 	else
   2819 	  _M_seq.insert(_M_seq.end(), __s.begin(), __s.end());
   2820 
   2821 	// Make the whole of _M_buf available for the next write:
   2822 	this->_M_rewind();
   2823       }
   2824 
   2825       typename _Sink<_CharT>::_Reservation
   2826       _M_reserve(size_t __n) override
   2827       {
   2828 	// We might already have n characters available in this->_M_unused(),
   2829 	// but the whole point of this function is to be an optimization for
   2830 	// the std::format("{}", x) case. We want to avoid writing to _M_buf
   2831 	// and then copying that into a basic_string if possible, so this
   2832 	// function prefers to create space directly in _M_seq rather than
   2833 	// using _M_buf.
   2834 
   2835 	if constexpr (__is_specialization_of<_Seq, basic_string>
   2836 			|| __is_specialization_of<_Seq, vector>)
   2837 	  {
   2838 	    // Flush the buffer to _M_seq first (should not be needed).
   2839 	    if (this->_M_used().size()) [[unlikely]]
   2840 	      _Seq_sink::_M_overflow();
   2841 
   2842 	    // Expand _M_seq to make __n new characters available:
   2843 	    const auto __sz = _M_seq.size();
   2844 	    if constexpr (is_same_v<string, _Seq> || is_same_v<wstring, _Seq>)
   2845 	      _M_seq.__resize_and_overwrite(__sz + __n,
   2846 					    [](auto, auto __n2) {
   2847 					      return __n2;
   2848 					    });
   2849 	    else
   2850 	      _M_seq.resize(__sz + __n);
   2851 
   2852 	    // Set _M_used() to be a span over the original part of _M_seq
   2853 	    // and _M_unused() to be the extra capacity we just created:
   2854 	    this->_M_reset(_M_seq, __sz);
   2855 	    return { this };
   2856 	  }
   2857 	else // Try to use the base class' buffer.
   2858 	  return _Sink<_CharT>::_M_reserve(__n);
   2859       }
   2860 
   2861       void
   2862       _M_bump(size_t __n) override
   2863       {
   2864 	if constexpr (__is_specialization_of<_Seq, basic_string>
   2865 			|| __is_specialization_of<_Seq, vector>)
   2866 	  {
   2867 	    auto __s = this->_M_used();
   2868 	    _GLIBCXX_DEBUG_ASSERT(__s.data() == _M_seq.data());
   2869 	    // Truncate the sequence to the part that was actually written to:
   2870 	    _M_seq.resize(__s.size() + __n);
   2871 	    // Switch back to using buffer:
   2872 	    this->_M_reset(this->_M_buf);
   2873 	  }
   2874       }
   2875 
   2876     public:
   2877       // TODO: for SSO string, use SSO buffer as initial span, then switch
   2878       // to _M_buf if it overflows? Or even do that for all unused capacity?
   2879 
   2880       [[__gnu__::__always_inline__]]
   2881       _Seq_sink() noexcept(is_nothrow_default_constructible_v<_Seq>)
   2882       { }
   2883 
   2884       _Seq_sink(_Seq&& __s) noexcept(is_nothrow_move_constructible_v<_Seq>)
   2885       : _M_seq(std::move(__s))
   2886       { }
   2887 
   2888       using _Sink<_CharT>::out;
   2889 
   2890       _Seq
   2891       get() &&
   2892       {
   2893 	if (this->_M_used().size() != 0)
   2894 	  _Seq_sink::_M_overflow();
   2895 	return std::move(_M_seq);
   2896       }
   2897 
   2898       // A writable span that views everything written to the sink.
   2899       // Will be either a view over _M_seq or the used part of _M_buf.
   2900       span<_CharT>
   2901       view()
   2902       {
   2903 	auto __s = this->_M_used();
   2904 	if (_M_seq.size())
   2905 	  {
   2906 	    if (__s.size() != 0)
   2907 	      _Seq_sink::_M_overflow();
   2908 	    return _M_seq;
   2909 	  }
   2910 	return __s;
   2911       }
   2912     };
   2913 
   2914   template<typename _CharT, typename _Alloc = allocator<_CharT>>
   2915     using _Str_sink
   2916       = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>;
   2917 
   2918   // template<typename _CharT, typename _Alloc = allocator<_CharT>>
   2919     // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>;
   2920 
   2921   // A sink that writes to an output iterator.
   2922   // Writes to a fixed-size buffer and then flushes to the output iterator
   2923   // when the buffer fills up.
   2924   template<typename _CharT, typename _OutIter>
   2925     class _Iter_sink : public _Buf_sink<_CharT>
   2926     {
   2927       _OutIter _M_out;
   2928       iter_difference_t<_OutIter> _M_max;
   2929 
   2930     protected:
   2931       size_t _M_count = 0;
   2932 
   2933       void
   2934       _M_overflow() override
   2935       {
   2936 	auto __s = this->_M_used();
   2937 	if (_M_max < 0) // No maximum.
   2938 	  _M_out = ranges::copy(__s, std::move(_M_out)).out;
   2939 	else if (_M_count < static_cast<size_t>(_M_max))
   2940 	  {
   2941 	    auto __max = _M_max - _M_count;
   2942 	    span<_CharT> __first;
   2943 	    if (__max < __s.size())
   2944 	      __first = __s.first(static_cast<size_t>(__max));
   2945 	    else
   2946 	      __first = __s;
   2947 	    _M_out = ranges::copy(__first, std::move(_M_out)).out;
   2948 	  }
   2949 	this->_M_rewind();
   2950 	_M_count += __s.size();
   2951       }
   2952 
   2953     public:
   2954       [[__gnu__::__always_inline__]]
   2955       explicit
   2956       _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __max = -1)
   2957       : _M_out(std::move(__out)), _M_max(__max)
   2958       { }
   2959 
   2960       using _Sink<_CharT>::out;
   2961 
   2962       format_to_n_result<_OutIter>
   2963       _M_finish() &&
   2964       {
   2965 	if (this->_M_used().size() != 0)
   2966 	  _Iter_sink::_M_overflow();
   2967 	iter_difference_t<_OutIter> __count(_M_count);
   2968 	return { std::move(_M_out), __count };
   2969       }
   2970     };
   2971 
   2972   // Partial specialization for contiguous iterators.
   2973   // No buffer is used, characters are written straight to the iterator.
   2974   // We do not know the size of the output range, so the span size just grows
   2975   // as needed. The end of the span might be an invalid pointer outside the
   2976   // valid range, but we never actually call _M_span.end(). This class does
   2977   // not introduce any invalid pointer arithmetic or overflows that would not
   2978   // have happened anyway.
   2979   template<typename _CharT, contiguous_iterator _OutIter>
   2980     requires same_as<iter_value_t<_OutIter>, _CharT>
   2981     class _Iter_sink<_CharT, _OutIter> : public _Sink<_CharT>
   2982     {
   2983       _OutIter _M_first;
   2984       iter_difference_t<_OutIter> _M_max = -1;
   2985     protected:
   2986       size_t _M_count = 0;
   2987     private:
   2988       _CharT _M_buf[64]; // Write here after outputting _M_max characters.
   2989 
   2990     protected:
   2991       void
   2992       _M_overflow() override
   2993       {
   2994 	if (this->_M_unused().size() != 0)
   2995 	  return; // No need to switch to internal buffer yet.
   2996 
   2997 	auto __s = this->_M_used();
   2998 
   2999 	if (_M_max >= 0)
   3000 	  {
   3001 	    _M_count += __s.size();
   3002 	    // Span was already sized for the maximum character count,
   3003 	    // if it overflows then any further output must go to the
   3004 	    // internal buffer, to be discarded.
   3005 	    this->_M_reset(this->_M_buf);
   3006 	  }
   3007 	else
   3008 	  {
   3009 	    // No maximum character count. Just extend the span to allow
   3010 	    // writing more characters to it.
   3011 	    this->_M_reset({__s.data(), __s.size() + 1024}, __s.size());
   3012 	  }
   3013       }
   3014 
   3015       typename _Sink<_CharT>::_Reservation
   3016       _M_reserve(size_t __n) final
   3017       {
   3018 	auto __avail = this->_M_unused();
   3019 	if (__n > __avail.size())
   3020 	  {
   3021 	    if (_M_max >= 0)
   3022 	      return {}; // cannot grow
   3023 
   3024 	    auto __s = this->_M_used();
   3025 	    this->_M_reset({__s.data(), __s.size() + __n}, __s.size());
   3026 	  }
   3027 	return { this };
   3028       }
   3029 
   3030     private:
   3031       static span<_CharT>
   3032       _S_make_span(_CharT* __ptr, iter_difference_t<_OutIter> __n,
   3033 		   span<_CharT> __buf) noexcept
   3034       {
   3035 	if (__n == 0)
   3036 	  return __buf; // Only write to the internal buffer.
   3037 
   3038 	if (__n > 0)
   3039 	  {
   3040 	    if constexpr (!is_integral_v<iter_difference_t<_OutIter>>
   3041 			    || sizeof(__n) > sizeof(size_t))
   3042 	      {
   3043 		// __int128 or __detail::__max_diff_type
   3044 		auto __m = iter_difference_t<_OutIter>((size_t)-1);
   3045 		if (__n > __m)
   3046 		  __n = __m;
   3047 	      }
   3048 	    return {__ptr, (size_t)__n};
   3049 	  }
   3050 
   3051 #if __has_builtin(__builtin_dynamic_object_size)
   3052 	if (size_t __bytes = __builtin_dynamic_object_size(__ptr, 2))
   3053 	  return {__ptr, __bytes / sizeof(_CharT)};
   3054 #endif
   3055 	// Avoid forming a pointer to a different memory page.
   3056 	const auto __off = reinterpret_cast<__UINTPTR_TYPE__>(__ptr) % 1024;
   3057 	__n = (1024 - __off) / sizeof(_CharT);
   3058 	if (__n > 0) [[likely]]
   3059 	  return {__ptr, static_cast<size_t>(__n)};
   3060 	else // Misaligned/packed buffer of wchar_t?
   3061 	  return {__ptr, 1};
   3062       }
   3063 
   3064     public:
   3065       explicit
   3066       _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __n = -1) noexcept
   3067       : _Sink<_CharT>(_S_make_span(std::to_address(__out), __n, _M_buf)),
   3068 	_M_first(__out), _M_max(__n)
   3069       { }
   3070 
   3071       format_to_n_result<_OutIter>
   3072       _M_finish() &&
   3073       {
   3074 	auto __s = this->_M_used();
   3075 	if (__s.data() == _M_buf)
   3076 	  {
   3077 	    // Switched to internal buffer, so must have written _M_max.
   3078 	    iter_difference_t<_OutIter> __count(_M_count + __s.size());
   3079 	    return { _M_first + _M_max, __count };
   3080 	  }
   3081 	else // Not using internal buffer yet
   3082 	  {
   3083 	    iter_difference_t<_OutIter> __count(__s.size());
   3084 	    return { _M_first + __count, __count };
   3085 	  }
   3086       }
   3087     };
   3088 
   3089   enum _Arg_t : unsigned char {
   3090     _Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull,
   3091     _Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr, _Arg_handle,
   3092     _Arg_i128, _Arg_u128,
   3093     _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, // These are unused.
   3094 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
   3095     _Arg_next_value_,
   3096     _Arg_f128 = _Arg_ldbl,
   3097     _Arg_ibm128 = _Arg_next_value_,
   3098 #else
   3099     _Arg_f128,
   3100 #endif
   3101     _Arg_max_
   3102   };
   3103 
   3104   template<typename _Context>
   3105     struct _Arg_value
   3106     {
   3107       using _CharT = typename _Context::char_type;
   3108 
   3109       struct _HandleBase
   3110       {
   3111 	const void* _M_ptr;
   3112 	void (*_M_func)();
   3113       };
   3114 
   3115       union
   3116       {
   3117 	monostate _M_none;
   3118 	bool _M_bool;
   3119 	_CharT _M_c;
   3120 	int _M_i;
   3121 	unsigned _M_u;
   3122 	long long _M_ll;
   3123 	unsigned long long _M_ull;
   3124 	float _M_flt;
   3125 	double _M_dbl;
   3126 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // No long double if it's ambiguous.
   3127 	long double _M_ldbl;
   3128 #endif
   3129 	const _CharT* _M_str;
   3130 	basic_string_view<_CharT> _M_sv;
   3131 	const void* _M_ptr;
   3132 	_HandleBase _M_handle;
   3133 #ifdef __SIZEOF_INT128__
   3134 	__int128 _M_i128;
   3135 	unsigned __int128 _M_u128;
   3136 #endif
   3137 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
   3138 	__ieee128 _M_f128;
   3139 	__ibm128  _M_ibm128;
   3140 #elif _GLIBCXX_FORMAT_F128 == 2
   3141 	__float128_t _M_f128;
   3142 #endif
   3143       };
   3144 
   3145       [[__gnu__::__always_inline__]]
   3146       _Arg_value() : _M_none() { }
   3147 
   3148 #if 0
   3149       template<typename _Tp>
   3150 	_Arg_value(in_place_type_t<_Tp>, _Tp __val)
   3151 	{ _S_get<_Tp>() = __val; }
   3152 #endif
   3153 
   3154       template<typename _Tp, typename _Self>
   3155 	[[__gnu__::__always_inline__]]
   3156 	static auto&
   3157 	_S_get(_Self& __u) noexcept
   3158 	{
   3159 	  if constexpr (is_same_v<_Tp, bool>)
   3160 	    return __u._M_bool;
   3161 	  else if constexpr (is_same_v<_Tp, _CharT>)
   3162 	    return __u._M_c;
   3163 	  else if constexpr (is_same_v<_Tp, int>)
   3164 	    return __u._M_i;
   3165 	  else if constexpr (is_same_v<_Tp, unsigned>)
   3166 	    return __u._M_u;
   3167 	  else if constexpr (is_same_v<_Tp, long long>)
   3168 	    return __u._M_ll;
   3169 	  else if constexpr (is_same_v<_Tp, unsigned long long>)
   3170 	    return __u._M_ull;
   3171 	  else if constexpr (is_same_v<_Tp, float>)
   3172 	    return __u._M_flt;
   3173 	  else if constexpr (is_same_v<_Tp, double>)
   3174 	    return __u._M_dbl;
   3175 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
   3176 	  else if constexpr (is_same_v<_Tp, long double>)
   3177 	    return __u._M_ldbl;
   3178 #else
   3179 	  else if constexpr (is_same_v<_Tp, __ieee128>)
   3180 	    return __u._M_f128;
   3181 	  else if constexpr (is_same_v<_Tp, __ibm128>)
   3182 	    return __u._M_ibm128;
   3183 #endif
   3184 	  else if constexpr (is_same_v<_Tp, const _CharT*>)
   3185 	    return __u._M_str;
   3186 	  else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
   3187 	    return __u._M_sv;
   3188 	  else if constexpr (is_same_v<_Tp, const void*>)
   3189 	    return __u._M_ptr;
   3190 #ifdef __SIZEOF_INT128__
   3191 	  else if constexpr (is_same_v<_Tp, __int128>)
   3192 	    return __u._M_i128;
   3193 	  else if constexpr (is_same_v<_Tp, unsigned __int128>)
   3194 	    return __u._M_u128;
   3195 #endif
   3196 #if _GLIBCXX_FORMAT_F128 == 2
   3197 	  else if constexpr (is_same_v<_Tp, __float128_t>)
   3198 	    return __u._M_f128;
   3199 #endif
   3200 	  else if constexpr (derived_from<_Tp, _HandleBase>)
   3201 	    return static_cast<_Tp&>(__u._M_handle);
   3202 	  // Otherwise, ill-formed.
   3203 	}
   3204 
   3205       template<typename _Tp>
   3206 	[[__gnu__::__always_inline__]]
   3207 	auto&
   3208 	_M_get() noexcept
   3209 	{ return _S_get<_Tp>(*this); }
   3210 
   3211       template<typename _Tp>
   3212 	[[__gnu__::__always_inline__]]
   3213 	const auto&
   3214 	_M_get() const noexcept
   3215 	{ return _S_get<_Tp>(*this); }
   3216 
   3217       template<typename _Tp>
   3218 	[[__gnu__::__always_inline__]]
   3219 	void
   3220 	_M_set(_Tp __v) noexcept
   3221 	{
   3222 	  if constexpr (derived_from<_Tp, _HandleBase>)
   3223 	    std::construct_at(&_M_handle, __v);
   3224 	  else
   3225 	    _S_get<_Tp>(*this) = __v;
   3226 	}
   3227       };
   3228 
   3229   // [format.arg.store], class template format-arg-store
   3230   template<typename _Context, typename... _Args>
   3231     class _Arg_store;
   3232 
   3233 } // namespace __format
   3234 /// @endcond
   3235 
   3236   template<typename _Context>
   3237     class basic_format_arg
   3238     {
   3239       using _CharT = typename _Context::char_type;
   3240 
   3241       template<typename _Tp>
   3242 	static constexpr bool __formattable
   3243 	  = __format::__formattable_with<_Tp, _Context>;
   3244 
   3245     public:
   3246       class handle : public __format::_Arg_value<_Context>::_HandleBase
   3247       {
   3248 	using _Base = typename __format::_Arg_value<_Context>::_HandleBase;
   3249 
   3250 	// Format as const if possible, to reduce instantiations.
   3251 	template<typename _Tp>
   3252 	  using __maybe_const_t
   3253 	    = __conditional_t<__formattable<const _Tp>, const _Tp, _Tp>;
   3254 
   3255 	template<typename _Tq>
   3256 	  static void
   3257 	  _S_format(basic_format_parse_context<_CharT>& __parse_ctx,
   3258 		    _Context& __format_ctx, const void* __ptr)
   3259 	  {
   3260 	    using _Td = remove_const_t<_Tq>;
   3261 	    typename _Context::template formatter_type<_Td> __f;
   3262 	    __parse_ctx.advance_to(__f.parse(__parse_ctx));
   3263 	    _Tq& __val = *const_cast<_Tq*>(static_cast<const _Td*>(__ptr));
   3264 	    __format_ctx.advance_to(__f.format(__val, __format_ctx));
   3265 	  }
   3266 
   3267 	template<typename _Tp>
   3268 	  explicit
   3269 	  handle(_Tp& __val) noexcept
   3270 	  {
   3271 	    this->_M_ptr = __builtin_addressof(__val);
   3272 	    auto __func = _S_format<__maybe_const_t<_Tp>>;
   3273 	    this->_M_func = reinterpret_cast<void(*)()>(__func);
   3274 	  }
   3275 
   3276 	friend class basic_format_arg<_Context>;
   3277 
   3278       public:
   3279 	handle(const handle&) = default;
   3280 	handle& operator=(const handle&) = default;
   3281 
   3282 	[[__gnu__::__always_inline__]]
   3283 	void
   3284 	format(basic_format_parse_context<_CharT>& __pc, _Context& __fc) const
   3285 	{
   3286 	  using _Func = void(*)(basic_format_parse_context<_CharT>&,
   3287 				_Context&, const void*);
   3288 	  auto __f = reinterpret_cast<_Func>(this->_M_func);
   3289 	  __f(__pc, __fc, this->_M_ptr);
   3290 	}
   3291       };
   3292 
   3293       [[__gnu__::__always_inline__]]
   3294       basic_format_arg() noexcept : _M_type(__format::_Arg_none) { }
   3295 
   3296       [[nodiscard,__gnu__::__always_inline__]]
   3297       explicit operator bool() const noexcept
   3298       { return _M_type != __format::_Arg_none; }
   3299 
   3300     private:
   3301       template<typename _Ctx>
   3302 	friend class basic_format_args;
   3303 
   3304       template<typename _Ctx, typename... _Args>
   3305 	friend class __format::_Arg_store;
   3306 
   3307       static_assert(is_trivially_copyable_v<__format::_Arg_value<_Context>>);
   3308 
   3309       __format::_Arg_value<_Context> _M_val;
   3310       __format::_Arg_t _M_type;
   3311 
   3312       // Transform incoming argument type to the type stored in _Arg_value.
   3313       // e.g. short -> int, std::string -> std::string_view,
   3314       // char[3] -> const char*.
   3315       template<typename _Tp>
   3316 	static consteval auto
   3317 	_S_to_arg_type()
   3318 	{
   3319 	  using _Td = remove_const_t<_Tp>;
   3320 	  if constexpr (is_same_v<_Td, bool>)
   3321 	    return type_identity<bool>();
   3322 	  else if constexpr (is_same_v<_Td, _CharT>)
   3323 	    return type_identity<_CharT>();
   3324 	  else if constexpr (is_same_v<_Td, char> && is_same_v<_CharT, wchar_t>)
   3325 	    return type_identity<_CharT>();
   3326 #ifdef __SIZEOF_INT128__ // Check before signed/unsigned integer
   3327 	  else if constexpr (is_same_v<_Td, __int128>)
   3328 	    return type_identity<__int128>();
   3329 	  else if constexpr (is_same_v<_Td, unsigned __int128>)
   3330 	    return type_identity<unsigned __int128>();
   3331 #endif
   3332 	  else if constexpr (__is_signed_integer<_Td>::value)
   3333 	    {
   3334 	      if constexpr (sizeof(_Td) <= sizeof(int))
   3335 		return type_identity<int>();
   3336 	      else if constexpr (sizeof(_Td) <= sizeof(long long))
   3337 		return type_identity<long long>();
   3338 	    }
   3339 	  else if constexpr (__is_unsigned_integer<_Td>::value)
   3340 	    {
   3341 	      if constexpr (sizeof(_Td) <= sizeof(unsigned))
   3342 		return type_identity<unsigned>();
   3343 	      else if constexpr (sizeof(_Td) <= sizeof(unsigned long long))
   3344 		return type_identity<unsigned long long>();
   3345 	    }
   3346 	  else if constexpr (is_same_v<_Td, float>)
   3347 	    return type_identity<float>();
   3348 	  else if constexpr (is_same_v<_Td, double>)
   3349 	    return type_identity<double>();
   3350 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
   3351 	  else if constexpr (is_same_v<_Td, long double>)
   3352 	    return type_identity<long double>();
   3353 #else
   3354 	  else if constexpr (is_same_v<_Td, __ibm128>)
   3355 	    return type_identity<__ibm128>();
   3356 	  else if constexpr (is_same_v<_Td, __ieee128>)
   3357 	    return type_identity<__ieee128>();
   3358 #endif
   3359 
   3360 #if defined(__FLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   3361 	  else if constexpr (is_same_v<_Td, _Float16>)
   3362 	    return type_identity<float>();
   3363 #endif
   3364 
   3365 #if defined(__BFLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   3366 	  else if constexpr (is_same_v<_Td, decltype(0.0bf16)>)
   3367 	    return type_identity<float>();
   3368 #endif
   3369 
   3370 #if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   3371 	  else if constexpr (is_same_v<_Td, _Float32>)
   3372 	    return type_identity<float>();
   3373 #endif
   3374 
   3375 #if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
   3376 	  else if constexpr (is_same_v<_Td, _Float64>)
   3377 	    return type_identity<double>();
   3378 #endif
   3379 
   3380 #if _GLIBCXX_FORMAT_F128
   3381 # if __FLT128_DIG__
   3382 	  else if constexpr (is_same_v<_Td, _Float128>)
   3383 	    return type_identity<__format::__float128_t>();
   3384 # endif
   3385 # if __SIZEOF_FLOAT128__
   3386 	  else if constexpr (is_same_v<_Td, __float128>)
   3387 	    return type_identity<__format::__float128_t>();
   3388 # endif
   3389 #endif
   3390 	  else if constexpr (__is_specialization_of<_Td, basic_string_view>
   3391 			    || __is_specialization_of<_Td, basic_string>)
   3392 	    {
   3393 	      if constexpr (is_same_v<typename _Td::value_type, _CharT>)
   3394 		return type_identity<basic_string_view<_CharT>>();
   3395 	      else
   3396 		return type_identity<handle>();
   3397 	    }
   3398 	  else if constexpr (is_same_v<decay_t<_Td>, const _CharT*>)
   3399 	    return type_identity<const _CharT*>();
   3400 	  else if constexpr (is_same_v<decay_t<_Td>, _CharT*>)
   3401 	    return type_identity<const _CharT*>();
   3402 	  else if constexpr (is_void_v<remove_pointer_t<_Td>>)
   3403 	    return type_identity<const void*>();
   3404 	  else if constexpr (is_same_v<_Td, nullptr_t>)
   3405 	    return type_identity<const void*>();
   3406 	  else
   3407 	    return type_identity<handle>();
   3408 	}
   3409 
   3410       // Transform a formattable type to the appropriate storage type.
   3411       template<typename _Tp>
   3412 	using _Normalize = typename decltype(_S_to_arg_type<_Tp>())::type;
   3413 
   3414       // Get the _Arg_t value corresponding to a normalized type.
   3415       template<typename _Tp>
   3416 	static consteval __format::_Arg_t
   3417 	_S_to_enum()
   3418 	{
   3419 	  using namespace __format;
   3420 	  if constexpr (is_same_v<_Tp, bool>)
   3421 	    return _Arg_bool;
   3422 	  else if constexpr (is_same_v<_Tp, _CharT>)
   3423 	    return _Arg_c;
   3424 	  else if constexpr (is_same_v<_Tp, int>)
   3425 	    return _Arg_i;
   3426 	  else if constexpr (is_same_v<_Tp, unsigned>)
   3427 	    return _Arg_u;
   3428 	  else if constexpr (is_same_v<_Tp, long long>)
   3429 	    return _Arg_ll;
   3430 	  else if constexpr (is_same_v<_Tp, unsigned long long>)
   3431 	    return _Arg_ull;
   3432 	  else if constexpr (is_same_v<_Tp, float>)
   3433 	    return _Arg_flt;
   3434 	  else if constexpr (is_same_v<_Tp, double>)
   3435 	    return _Arg_dbl;
   3436 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
   3437 	  else if constexpr (is_same_v<_Tp, long double>)
   3438 	    return _Arg_ldbl;
   3439 #else
   3440 	  // Don't use _Arg_ldbl for this target, it's ambiguous.
   3441 	  else if constexpr (is_same_v<_Tp, __ibm128>)
   3442 	    return _Arg_ibm128;
   3443 	  else if constexpr (is_same_v<_Tp, __ieee128>)
   3444 	    return _Arg_f128;
   3445 #endif
   3446 	  else if constexpr (is_same_v<_Tp, const _CharT*>)
   3447 	    return _Arg_str;
   3448 	  else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
   3449 	    return _Arg_sv;
   3450 	  else if constexpr (is_same_v<_Tp, const void*>)
   3451 	    return _Arg_ptr;
   3452 #ifdef __SIZEOF_INT128__
   3453 	  else if constexpr (is_same_v<_Tp, __int128>)
   3454 	    return _Arg_i128;
   3455 	  else if constexpr (is_same_v<_Tp, unsigned __int128>)
   3456 	    return _Arg_u128;
   3457 #endif
   3458 
   3459 #if _GLIBCXX_FORMAT_F128 == 2
   3460 	  else if constexpr (is_same_v<_Tp, __format::__float128_t>)
   3461 	    return _Arg_f128;
   3462 #endif
   3463 	  else if constexpr (is_same_v<_Tp, handle>)
   3464 	    return _Arg_handle;
   3465 	}
   3466 
   3467       template<typename _Tp>
   3468 	void
   3469 	_M_set(_Tp __v) noexcept
   3470 	{
   3471 	  _M_type = _S_to_enum<_Tp>();
   3472 	  _M_val._M_set(__v);
   3473 	}
   3474 
   3475       template<typename _Tp>
   3476 	requires __format::__formattable_with<_Tp, _Context>
   3477 	explicit
   3478 	basic_format_arg(_Tp& __v) noexcept
   3479 	{
   3480 	  using _Td = _Normalize<_Tp>;
   3481 	  if constexpr (is_same_v<_Td, basic_string_view<_CharT>>)
   3482 	    _M_set(_Td{__v.data(), __v.size()});
   3483 	  else if constexpr (is_same_v<remove_const_t<_Tp>, char>
   3484 			       && is_same_v<_CharT, wchar_t>)
   3485 	    _M_set(static_cast<_Td>(static_cast<unsigned char>(__v)));
   3486 	  else
   3487 	    _M_set(static_cast<_Td>(__v));
   3488 	}
   3489 
   3490       template<typename _Ctx, typename... _Argz>
   3491 	friend auto
   3492 	make_format_args(_Argz&...) noexcept;
   3493 
   3494       template<typename _Visitor, typename _Ctx>
   3495 	friend decltype(auto)
   3496 	visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx>);
   3497 
   3498       template<typename _Visitor>
   3499 	decltype(auto)
   3500 	_M_visit(_Visitor&& __vis, __format::_Arg_t __type)
   3501 	{
   3502 	  using namespace __format;
   3503 	  switch (__type)
   3504 	  {
   3505 	    case _Arg_none:
   3506 	      return std::forward<_Visitor>(__vis)(_M_val._M_none);
   3507 	    case _Arg_bool:
   3508 	      return std::forward<_Visitor>(__vis)(_M_val._M_bool);
   3509 	    case _Arg_c:
   3510 	      return std::forward<_Visitor>(__vis)(_M_val._M_c);
   3511 	    case _Arg_i:
   3512 	      return std::forward<_Visitor>(__vis)(_M_val._M_i);
   3513 	    case _Arg_u:
   3514 	      return std::forward<_Visitor>(__vis)(_M_val._M_u);
   3515 	    case _Arg_ll:
   3516 	      return std::forward<_Visitor>(__vis)(_M_val._M_ll);
   3517 	    case _Arg_ull:
   3518 	      return std::forward<_Visitor>(__vis)(_M_val._M_ull);
   3519 #if __glibcxx_to_chars // FIXME: need to be able to format these types!
   3520 	    case _Arg_flt:
   3521 	      return std::forward<_Visitor>(__vis)(_M_val._M_flt);
   3522 	    case _Arg_dbl:
   3523 	      return std::forward<_Visitor>(__vis)(_M_val._M_dbl);
   3524 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
   3525 	    case _Arg_ldbl:
   3526 	      return std::forward<_Visitor>(__vis)(_M_val._M_ldbl);
   3527 #else
   3528 	    case _Arg_f128:
   3529 	      return std::forward<_Visitor>(__vis)(_M_val._M_f128);
   3530 	    case _Arg_ibm128:
   3531 	      return std::forward<_Visitor>(__vis)(_M_val._M_ibm128);
   3532 #endif
   3533 #endif
   3534 	    case _Arg_str:
   3535 	      return std::forward<_Visitor>(__vis)(_M_val._M_str);
   3536 	    case _Arg_sv:
   3537 	      return std::forward<_Visitor>(__vis)(_M_val._M_sv);
   3538 	    case _Arg_ptr:
   3539 	      return std::forward<_Visitor>(__vis)(_M_val._M_ptr);
   3540 	    case _Arg_handle:
   3541 	    {
   3542 	      auto& __h = static_cast<handle&>(_M_val._M_handle);
   3543 	      return std::forward<_Visitor>(__vis)(__h);
   3544 	    }
   3545 #ifdef __SIZEOF_INT128__
   3546 	    case _Arg_i128:
   3547 	      return std::forward<_Visitor>(__vis)(_M_val._M_i128);
   3548 	    case _Arg_u128:
   3549 	      return std::forward<_Visitor>(__vis)(_M_val._M_u128);
   3550 #endif
   3551 
   3552 #if _GLIBCXX_FORMAT_F128 == 2
   3553 	    case _Arg_f128:
   3554 	      return std::forward<_Visitor>(__vis)(_M_val._M_f128);
   3555 #endif
   3556 
   3557 	    default:
   3558 	      // _Arg_f16 etc.
   3559 	      __builtin_unreachable();
   3560 	  }
   3561 	}
   3562     };
   3563 
   3564   template<typename _Visitor, typename _Context>
   3565     inline decltype(auto)
   3566     visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
   3567     {
   3568       return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type);
   3569     }
   3570 
   3571 /// @cond undocumented
   3572 namespace __format
   3573 {
   3574   struct _WidthPrecVisitor
   3575   {
   3576     template<typename _Tp>
   3577       size_t
   3578       operator()(_Tp& __arg) const
   3579       {
   3580 	if constexpr (is_same_v<_Tp, monostate>)
   3581 	  __format::__invalid_arg_id_in_format_string();
   3582 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
   3583 	// 3720. Restrict the valid types of arg-id for width and precision
   3584 	// 3721. Allow an arg-id with a value of zero for width
   3585 	else if constexpr (sizeof(_Tp) <= sizeof(long long))
   3586 	  {
   3587 	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
   3588 	    // 3720. Restrict the valid types of arg-id for width and precision
   3589 	    if constexpr (__is_unsigned_integer<_Tp>::value)
   3590 	      return __arg;
   3591 	    else if constexpr (__is_signed_integer<_Tp>::value)
   3592 	      if (__arg >= 0)
   3593 		return __arg;
   3594 	  }
   3595 	__throw_format_error("format error: argument used for width or "
   3596 			     "precision must be a non-negative integer");
   3597       }
   3598   };
   3599 
   3600   template<typename _Context>
   3601     inline size_t
   3602     __int_from_arg(const basic_format_arg<_Context>& __arg)
   3603     { return std::visit_format_arg(_WidthPrecVisitor(), __arg); }
   3604 
   3605   // Pack _Arg_t enum values into a single 60-bit integer.
   3606   template<int _Bits, size_t _Nm>
   3607     constexpr auto
   3608     __pack_arg_types(const array<_Arg_t, _Nm>& __types)
   3609     {
   3610       __UINT64_TYPE__ __packed_types = 0;
   3611       for (auto __i = __types.rbegin(); __i != __types.rend(); ++__i)
   3612 	__packed_types = (__packed_types << _Bits) | *__i;
   3613       return __packed_types;
   3614     }
   3615 } // namespace __format
   3616 /// @endcond
   3617 
   3618   template<typename _Context>
   3619     class basic_format_args
   3620     {
   3621       static constexpr int _S_packed_type_bits = 5; // _Arg_t values [0,20]
   3622       static constexpr int _S_packed_type_mask = 0b11111;
   3623       static constexpr int _S_max_packed_args = 12;
   3624 
   3625       static_assert( __format::_Arg_max_ <= (1 << _S_packed_type_bits) );
   3626 
   3627       template<typename... _Args>
   3628 	using _Store = __format::_Arg_store<_Context, _Args...>;
   3629 
   3630       template<typename _Ctx, typename... _Args>
   3631 	friend class __format::_Arg_store;
   3632 
   3633       using uint64_t = __UINT64_TYPE__;
   3634       using _Format_arg = basic_format_arg<_Context>;
   3635       using _Format_arg_val = __format::_Arg_value<_Context>;
   3636 
   3637       // If args are packed then the number of args is in _M_packed_size and
   3638       // the packed types are in _M_unpacked_size, accessed via _M_type(i).
   3639       // If args are not packed then the number of args is in _M_unpacked_size
   3640       // and _M_packed_size is zero.
   3641       uint64_t _M_packed_size : 4;
   3642       uint64_t _M_unpacked_size : 60;
   3643 
   3644       union {
   3645 	const _Format_arg_val* _M_values; // Active when _M_packed_size != 0
   3646 	const _Format_arg* _M_args;       // Active when _M_packed_size == 0
   3647       };
   3648 
   3649       size_t
   3650       _M_size() const noexcept
   3651       { return _M_packed_size ? _M_packed_size : _M_unpacked_size; }
   3652 
   3653       typename __format::_Arg_t
   3654       _M_type(size_t __i) const noexcept
   3655       {
   3656 	uint64_t __t = _M_unpacked_size >> (__i * _S_packed_type_bits);
   3657 	return static_cast<__format::_Arg_t>(__t & _S_packed_type_mask);
   3658       }
   3659 
   3660       template<typename _Ctx, typename... _Args>
   3661 	friend auto
   3662 	make_format_args(_Args&...) noexcept;
   3663 
   3664       // An array of _Arg_t enums corresponding to _Args...
   3665       template<typename... _Args>
   3666 	static consteval array<__format::_Arg_t, sizeof...(_Args)>
   3667 	_S_types_to_pack()
   3668 	{ return {_Format_arg::template _S_to_enum<_Args>()...}; }
   3669 
   3670     public:
   3671       template<typename... _Args>
   3672 	basic_format_args(const _Store<_Args...>& __store) noexcept;
   3673 
   3674       [[nodiscard,__gnu__::__always_inline__]]
   3675       basic_format_arg<_Context>
   3676       get(size_t __i) const noexcept
   3677       {
   3678 	basic_format_arg<_Context> __arg;
   3679 	if (__i < _M_packed_size)
   3680 	  {
   3681 	    __arg._M_type = _M_type(__i);
   3682 	    __arg._M_val = _M_values[__i];
   3683 	  }
   3684 	else if (_M_packed_size == 0 && __i < _M_unpacked_size)
   3685 	  __arg = _M_args[__i];
   3686 	return __arg;
   3687       }
   3688     };
   3689 
   3690   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   3691   // 3810. CTAD for std::basic_format_args
   3692   template<typename _Context, typename... _Args>
   3693     basic_format_args(__format::_Arg_store<_Context, _Args...>)
   3694       -> basic_format_args<_Context>;
   3695 
   3696   template<typename _Context, typename... _Args>
   3697     auto
   3698     make_format_args(_Args&... __fmt_args) noexcept;
   3699 
   3700   // An array of type-erased formatting arguments.
   3701   template<typename _Context, typename... _Args>
   3702     class __format::_Arg_store
   3703     {
   3704       friend std::basic_format_args<_Context>;
   3705 
   3706       template<typename _Ctx, typename... _Argz>
   3707 	friend auto std::
   3708 #if _GLIBCXX_INLINE_VERSION
   3709 	__8:: // Needed for PR c++/59256
   3710 #endif
   3711 	make_format_args(_Argz&...) noexcept;
   3712 
   3713       // For a sufficiently small number of arguments we only store values.
   3714       // basic_format_args can get the types from the _Args pack.
   3715       static constexpr bool _S_values_only
   3716 	= sizeof...(_Args) <= basic_format_args<_Context>::_S_max_packed_args;
   3717 
   3718       using _Element_t
   3719 	= __conditional_t<_S_values_only,
   3720 			  __format::_Arg_value<_Context>,
   3721 			  basic_format_arg<_Context>>;
   3722 
   3723       _Element_t _M_args[sizeof...(_Args)];
   3724 
   3725       template<typename _Tp>
   3726 	static _Element_t
   3727 	_S_make_elt(_Tp& __v)
   3728 	{
   3729 	  using _Tq = remove_const_t<_Tp>;
   3730 	  using _CharT = typename _Context::char_type;
   3731 	  static_assert(is_default_constructible_v<formatter<_Tq, _CharT>>,
   3732 			"std::formatter must be specialized for the type "
   3733 			"of each format arg");
   3734 	  using __format::__formattable_with;
   3735 	  if constexpr (is_const_v<_Tp>)
   3736 	    if constexpr (!__formattable_with<_Tp, _Context>)
   3737 	      if constexpr (__formattable_with<_Tq, _Context>)
   3738 		static_assert(__formattable_with<_Tp, _Context>,
   3739 			      "format arg must be non-const because its "
   3740 			      "std::formatter specialization has a "
   3741 			      "non-const reference parameter");
   3742 	  basic_format_arg<_Context> __arg(__v);
   3743 	  if constexpr (_S_values_only)
   3744 	    return __arg._M_val;
   3745 	  else
   3746 	    return __arg;
   3747 	}
   3748 
   3749       template<typename... _Tp>
   3750 	requires (sizeof...(_Tp) == sizeof...(_Args))
   3751 	[[__gnu__::__always_inline__]]
   3752 	_Arg_store(_Tp&... __a) noexcept
   3753 	: _M_args{_S_make_elt(__a)...}
   3754 	{ }
   3755     };
   3756 
   3757   template<typename _Context>
   3758     class __format::_Arg_store<_Context>
   3759     { };
   3760 
   3761   template<typename _Context>
   3762     template<typename... _Args>
   3763       inline
   3764       basic_format_args<_Context>::
   3765       basic_format_args(const _Store<_Args...>& __store) noexcept
   3766       {
   3767 	if constexpr (sizeof...(_Args) == 0)
   3768 	  {
   3769 	    _M_packed_size = 0;
   3770 	    _M_unpacked_size = 0;
   3771 	    _M_args = nullptr;
   3772 	  }
   3773 	else if constexpr (sizeof...(_Args) <= _S_max_packed_args)
   3774 	  {
   3775 	    // The number of packed arguments:
   3776 	    _M_packed_size = sizeof...(_Args);
   3777 	    // The packed type enums:
   3778 	    _M_unpacked_size
   3779 	      = __format::__pack_arg_types<_S_packed_type_bits>(_S_types_to_pack<_Args...>());
   3780 	    // The _Arg_value objects.
   3781 	    _M_values = __store._M_args;
   3782 	  }
   3783 	else
   3784 	  {
   3785 	    // No packed arguments:
   3786 	    _M_packed_size = 0;
   3787 	    // The number of unpacked arguments:
   3788 	    _M_unpacked_size = sizeof...(_Args);
   3789 	    // The basic_format_arg objects:
   3790 	    _M_args = __store._M_args;
   3791 	  }
   3792       }
   3793 
   3794   /// Capture formatting arguments for use by `std::vformat`.
   3795   template<typename _Context = format_context, typename... _Args>
   3796     [[nodiscard,__gnu__::__always_inline__]]
   3797     inline auto
   3798     make_format_args(_Args&... __fmt_args) noexcept
   3799     {
   3800       using _Fmt_arg = basic_format_arg<_Context>;
   3801       using _Store = __format::_Arg_store<_Context, typename _Fmt_arg::template
   3802 		     _Normalize<_Args>...>;
   3803       return _Store(__fmt_args...);
   3804     }
   3805 
   3806 #ifdef _GLIBCXX_USE_WCHAR_T
   3807   /// Capture formatting arguments for use by `std::vformat` (for wide output).
   3808   template<typename... _Args>
   3809     [[nodiscard,__gnu__::__always_inline__]]
   3810     inline auto
   3811     make_wformat_args(_Args&... __args) noexcept
   3812     { return std::make_format_args<wformat_context>(__args...); }
   3813 #endif
   3814 
   3815 /// @cond undocumented
   3816 namespace __format
   3817 {
   3818   template<typename _Out, typename _CharT, typename _Context>
   3819     _Out
   3820     __do_vformat_to(_Out, basic_string_view<_CharT>,
   3821 		    const basic_format_args<_Context>&,
   3822 		    const locale* = nullptr);
   3823 } // namespace __format
   3824 /// @endcond
   3825 
   3826   /** Context for std::format and similar functions.
   3827    *
   3828    * A formatting context contains an output iterator and locale to use
   3829    * for the formatting operations. Most programs will never need to use
   3830    * this class template explicitly. For typical uses of `std::format` the
   3831    * library will use the specializations `std::format_context` (for `char`)
   3832    * and `std::wformat_context` (for `wchar_t`).
   3833    */
   3834   template<typename _Out, typename _CharT>
   3835     class basic_format_context
   3836     {
   3837       static_assert( output_iterator<_Out, const _CharT&> );
   3838 
   3839       basic_format_args<basic_format_context> _M_args;
   3840       _Out _M_out;
   3841       __format::_Optional_locale _M_loc;
   3842 
   3843       basic_format_context(basic_format_args<basic_format_context> __args,
   3844 			   _Out __out)
   3845       : _M_args(__args), _M_out(std::move(__out))
   3846       { }
   3847 
   3848       basic_format_context(basic_format_args<basic_format_context> __args,
   3849 			   _Out __out, const std::locale& __loc)
   3850       : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
   3851       { }
   3852 
   3853       // _GLIBCXX_RESOLVE_LIB_DEFECTS
   3854       // 4061. Should std::basic_format_context be
   3855       //       default-constructible/copyable/movable?
   3856       basic_format_context(const basic_format_context&) = delete;
   3857       basic_format_context& operator=(const basic_format_context&) = delete;
   3858 
   3859       template<typename _Out2, typename _CharT2, typename _Context2>
   3860 	friend _Out2
   3861 	__format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
   3862 				  const basic_format_args<_Context2>&,
   3863 				  const locale*);
   3864 
   3865     public:
   3866       ~basic_format_context() = default;
   3867 
   3868       using iterator = _Out;
   3869       using char_type = _CharT;
   3870       template<typename _Tp>
   3871 	using formatter_type = formatter<_Tp, _CharT>;
   3872 
   3873       [[nodiscard]]
   3874       basic_format_arg<basic_format_context>
   3875       arg(size_t __id) const noexcept
   3876       { return _M_args.get(__id); }
   3877 
   3878       [[nodiscard]]
   3879       std::locale locale() { return _M_loc.value(); }
   3880 
   3881       [[nodiscard]]
   3882       iterator out() { return std::move(_M_out); }
   3883 
   3884       void advance_to(iterator __it) { _M_out = std::move(__it); }
   3885     };
   3886 
   3887 
   3888 /// @cond undocumented
   3889 namespace __format
   3890 {
   3891   // Abstract base class defining an interface for scanning format strings.
   3892   // Scan the characters in a format string, dividing it up into strings of
   3893   // ordinary characters, escape sequences, and replacement fields.
   3894   // Call virtual functions for derived classes to parse format-specifiers
   3895   // or write formatted output.
   3896   template<typename _CharT>
   3897     struct _Scanner
   3898     {
   3899       using iterator = typename basic_format_parse_context<_CharT>::iterator;
   3900 
   3901       basic_format_parse_context<_CharT> _M_pc;
   3902 
   3903       constexpr explicit
   3904       _Scanner(basic_string_view<_CharT> __str, size_t __nargs = (size_t)-1)
   3905       : _M_pc(__str, __nargs)
   3906       { }
   3907 
   3908       constexpr iterator begin() const noexcept { return _M_pc.begin(); }
   3909       constexpr iterator end() const noexcept { return _M_pc.end(); }
   3910 
   3911       constexpr void
   3912       _M_scan()
   3913       {
   3914 	basic_string_view<_CharT> __fmt = _M_fmt_str();
   3915 
   3916 	if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
   3917 	  {
   3918 	    _M_pc.advance_to(begin() + 1);
   3919 	    _M_format_arg(_M_pc.next_arg_id());
   3920 	    return;
   3921 	  }
   3922 
   3923 	size_t __lbr = __fmt.find('{');
   3924 	size_t __rbr = __fmt.find('}');
   3925 
   3926 	while (__fmt.size())
   3927 	  {
   3928 	    auto __cmp = __lbr <=> __rbr;
   3929 	    if (__cmp == 0)
   3930 	      {
   3931 		_M_on_chars(end());
   3932 		_M_pc.advance_to(end());
   3933 		return;
   3934 	      }
   3935 	    else if (__cmp < 0)
   3936 	      {
   3937 		if (__lbr + 1 == __fmt.size()
   3938 		      || (__rbr == __fmt.npos && __fmt[__lbr + 1] != '{'))
   3939 		  __format::__unmatched_left_brace_in_format_string();
   3940 		const bool __is_escape = __fmt[__lbr + 1] == '{';
   3941 		iterator __last = begin() + __lbr + int(__is_escape);
   3942 		_M_on_chars(__last);
   3943 		_M_pc.advance_to(__last + 1);
   3944 		__fmt = _M_fmt_str();
   3945 		if (__is_escape)
   3946 		  {
   3947 		    if (__rbr != __fmt.npos)
   3948 		      __rbr -= __lbr + 2;
   3949 		    __lbr = __fmt.find('{');
   3950 		  }
   3951 		else
   3952 		  {
   3953 		    _M_on_replacement_field();
   3954 		    __fmt = _M_fmt_str();
   3955 		    __lbr = __fmt.find('{');
   3956 		    __rbr = __fmt.find('}');
   3957 		  }
   3958 	      }
   3959 	    else
   3960 	      {
   3961 		if (++__rbr == __fmt.size() || __fmt[__rbr] != '}')
   3962 		  __format::__unmatched_right_brace_in_format_string();
   3963 		iterator __last = begin() + __rbr;
   3964 		_M_on_chars(__last);
   3965 		_M_pc.advance_to(__last + 1);
   3966 		__fmt = _M_fmt_str();
   3967 		if (__lbr != __fmt.npos)
   3968 		  __lbr -= __rbr + 1;
   3969 		__rbr = __fmt.find('}');
   3970 	      }
   3971 	  }
   3972       }
   3973 
   3974       constexpr basic_string_view<_CharT>
   3975       _M_fmt_str() const noexcept
   3976       { return {begin(), end()}; }
   3977 
   3978       constexpr virtual void _M_on_chars(iterator) { }
   3979 
   3980       constexpr void _M_on_replacement_field()
   3981       {
   3982 	auto __next = begin();
   3983 
   3984 	size_t __id;
   3985 	if (*__next == '}')
   3986 	  __id = _M_pc.next_arg_id();
   3987 	else if (*__next == ':')
   3988 	  {
   3989 	    __id = _M_pc.next_arg_id();
   3990 	    _M_pc.advance_to(++__next);
   3991 	  }
   3992 	else
   3993 	  {
   3994 	    auto [__i, __ptr] = __format::__parse_arg_id(begin(), end());
   3995 	    if (!__ptr || !(*__ptr == '}' || *__ptr == ':'))
   3996 	      __format::__invalid_arg_id_in_format_string();
   3997 	    _M_pc.check_arg_id(__id = __i);
   3998 	    if (*__ptr == ':')
   3999 	      {
   4000 		_M_pc.advance_to(++__ptr);
   4001 	      }
   4002 	    else
   4003 	      _M_pc.advance_to(__ptr);
   4004 	  }
   4005 	_M_format_arg(__id);
   4006 	if (begin() == end() || *begin() != '}')
   4007 	  __format::__unmatched_left_brace_in_format_string();
   4008 	_M_pc.advance_to(begin() + 1); // Move past '}'
   4009       }
   4010 
   4011       constexpr virtual void _M_format_arg(size_t __id) = 0;
   4012     };
   4013 
   4014   // Process a format string and format the arguments in the context.
   4015   template<typename _Out, typename _CharT>
   4016     class _Formatting_scanner : public _Scanner<_CharT>
   4017     {
   4018     public:
   4019       _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
   4020 			  basic_string_view<_CharT> __str)
   4021       : _Scanner<_CharT>(__str), _M_fc(__fc)
   4022       { }
   4023 
   4024     private:
   4025       basic_format_context<_Out, _CharT>& _M_fc;
   4026 
   4027       using iterator = typename _Scanner<_CharT>::iterator;
   4028 
   4029       constexpr void
   4030       _M_on_chars(iterator __last) override
   4031       {
   4032 	basic_string_view<_CharT> __str(this->begin(), __last);
   4033 	_M_fc.advance_to(__format::__write(_M_fc.out(), __str));
   4034       }
   4035 
   4036       constexpr void
   4037       _M_format_arg(size_t __id) override
   4038       {
   4039 	using _Context = basic_format_context<_Out, _CharT>;
   4040 	using handle = typename basic_format_arg<_Context>::handle;
   4041 
   4042 	std::visit_format_arg([this](auto& __arg) {
   4043 	  using _Type = remove_reference_t<decltype(__arg)>;
   4044 	  using _Formatter = typename _Context::template formatter_type<_Type>;
   4045 	  if constexpr (is_same_v<_Type, monostate>)
   4046 	    __format::__invalid_arg_id_in_format_string();
   4047 	  else if constexpr (is_same_v<_Type, handle>)
   4048 	    __arg.format(this->_M_pc, this->_M_fc);
   4049 	  else if constexpr (is_default_constructible_v<_Formatter>)
   4050 	    {
   4051 	      _Formatter __f;
   4052 	      this->_M_pc.advance_to(__f.parse(this->_M_pc));
   4053 	      this->_M_fc.advance_to(__f.format(__arg, this->_M_fc));
   4054 	    }
   4055 	  else
   4056 	    static_assert(__format::__formattable_with<_Type, _Context>);
   4057 	}, _M_fc.arg(__id));
   4058       }
   4059     };
   4060 
   4061   // Validate a format string for Args.
   4062   template<typename _CharT, typename... _Args>
   4063     class _Checking_scanner : public _Scanner<_CharT>
   4064     {
   4065       static_assert(
   4066 	(is_default_constructible_v<formatter<_Args, _CharT>> && ...),
   4067 	"std::formatter must be specialized for each type being formatted");
   4068 
   4069     public:
   4070       constexpr
   4071       _Checking_scanner(basic_string_view<_CharT> __str)
   4072       : _Scanner<_CharT>(__str, sizeof...(_Args))
   4073       { }
   4074 
   4075     private:
   4076       constexpr void
   4077       _M_format_arg(size_t __id) override
   4078       {
   4079 	if constexpr (sizeof...(_Args) != 0)
   4080 	  {
   4081 	    if (__id < sizeof...(_Args))
   4082 	      {
   4083 		_M_parse_format_spec<_Args...>(__id);
   4084 		return;
   4085 	      }
   4086 	  }
   4087 	__builtin_unreachable();
   4088       }
   4089 
   4090       template<typename _Tp, typename... _OtherArgs>
   4091 	constexpr void
   4092 	_M_parse_format_spec(size_t __id)
   4093 	{
   4094 	  if (__id == 0)
   4095 	    {
   4096 	      formatter<_Tp, _CharT> __f;
   4097 	      this->_M_pc.advance_to(__f.parse(this->_M_pc));
   4098 	    }
   4099 	  else if constexpr (sizeof...(_OtherArgs) != 0)
   4100 	    _M_parse_format_spec<_OtherArgs...>(__id - 1);
   4101 	  else
   4102 	    __builtin_unreachable();
   4103 	}
   4104     };
   4105 
   4106   template<typename _Out, typename _CharT, typename _Context>
   4107     inline _Out
   4108     __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
   4109 		    const basic_format_args<_Context>& __args,
   4110 		    const locale* __loc)
   4111     {
   4112       _Iter_sink<_CharT, _Out> __sink(std::move(__out));
   4113       _Sink_iter<_CharT> __sink_out;
   4114 
   4115       if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
   4116 	__sink_out = __out; // Already a sink iterator, safe to use post-move.
   4117       else
   4118 	__sink_out = __sink.out();
   4119 
   4120       if constexpr (is_same_v<_CharT, char>)
   4121 	// Fast path for "{}" format strings and simple format arg types.
   4122 	if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
   4123 	  {
   4124 	    bool __done = false;
   4125 	    std::visit_format_arg([&](auto& __arg) {
   4126 	      using _Tp = remove_cvref_t<decltype(__arg)>;
   4127 	      if constexpr (is_same_v<_Tp, bool>)
   4128 		{
   4129 		  size_t __len = 4 + !__arg;
   4130 		  const char* __chars[] = { "false", "true" };
   4131 		  if (auto __res = __sink_out._M_reserve(__len))
   4132 		    {
   4133 		      __builtin_memcpy(__res.get(), __chars[__arg], __len);
   4134 		      __res._M_bump(__len);
   4135 		      __done = true;
   4136 		    }
   4137 		}
   4138 	      else if constexpr (is_same_v<_Tp, char>)
   4139 		{
   4140 		  if (auto __res = __sink_out._M_reserve(1))
   4141 		    {
   4142 		      *__res.get() = __arg;
   4143 		      __res._M_bump(1);
   4144 		      __done = true;
   4145 		    }
   4146 		}
   4147 	      else if constexpr (is_integral_v<_Tp>)
   4148 		{
   4149 		  make_unsigned_t<_Tp> __uval;
   4150 		  const bool __neg = __arg < 0;
   4151 		  if (__neg)
   4152 		    __uval = make_unsigned_t<_Tp>(~__arg) + 1u;
   4153 		  else
   4154 		    __uval = __arg;
   4155 		  const auto __n = __detail::__to_chars_len(__uval);
   4156 		  if (auto __res = __sink_out._M_reserve(__n + __neg))
   4157 		    {
   4158 		      auto __ptr = __res.get();
   4159 		      *__ptr = '-';
   4160 		      __detail::__to_chars_10_impl(__ptr + (int)__neg, __n,
   4161 						   __uval);
   4162 		      __res._M_bump(__n + __neg);
   4163 		      __done = true;
   4164 		    }
   4165 		}
   4166 	      else if constexpr (is_convertible_v<_Tp, string_view>)
   4167 		{
   4168 		  string_view __sv = __arg;
   4169 		  if (auto __res = __sink_out._M_reserve(__sv.size()))
   4170 		    {
   4171 		      __builtin_memcpy(__res.get(), __sv.data(), __sv.size());
   4172 		      __res._M_bump(__sv.size());
   4173 		      __done = true;
   4174 		    }
   4175 		}
   4176 	    }, __args.get(0));
   4177 
   4178 	    if (__done)
   4179 	      {
   4180 		if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
   4181 		  return __sink_out;
   4182 		else
   4183 		  return std::move(__sink)._M_finish().out;
   4184 	      }
   4185 	  }
   4186 
   4187       auto __ctx = __loc == nullptr
   4188 		     ? _Context(__args, __sink_out)
   4189 		     : _Context(__args, __sink_out, *__loc);
   4190       _Formatting_scanner<_Sink_iter<_CharT>, _CharT> __scanner(__ctx, __fmt);
   4191       __scanner._M_scan();
   4192 
   4193       if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
   4194 	return __ctx.out();
   4195       else
   4196 	return std::move(__sink)._M_finish().out;
   4197     }
   4198 
   4199 } // namespace __format
   4200 /// @endcond
   4201 
   4202   template<typename _CharT, typename... _Args>
   4203     template<typename _Tp>
   4204       requires convertible_to<const _Tp&, basic_string_view<_CharT>>
   4205       consteval
   4206       basic_format_string<_CharT, _Args...>::
   4207       basic_format_string(const _Tp& __s)
   4208       : _M_str(__s)
   4209       {
   4210 	__format::_Checking_scanner<_CharT, remove_cvref_t<_Args>...>
   4211 	  __scanner(_M_str);
   4212 	__scanner._M_scan();
   4213       }
   4214 
   4215   // [format.functions], formatting functions
   4216 
   4217   template<typename _Out> requires output_iterator<_Out, const char&>
   4218     [[__gnu__::__always_inline__]]
   4219     inline _Out
   4220     vformat_to(_Out __out, string_view __fmt, format_args __args)
   4221     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
   4222 
   4223 #ifdef _GLIBCXX_USE_WCHAR_T
   4224   template<typename _Out> requires output_iterator<_Out, const wchar_t&>
   4225     [[__gnu__::__always_inline__]]
   4226     inline _Out
   4227     vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
   4228     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
   4229 #endif
   4230 
   4231   template<typename _Out> requires output_iterator<_Out, const char&>
   4232     [[__gnu__::__always_inline__]]
   4233     inline _Out
   4234     vformat_to(_Out __out, const locale& __loc, string_view __fmt,
   4235 	       format_args __args)
   4236     {
   4237       return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
   4238     }
   4239 
   4240 #ifdef _GLIBCXX_USE_WCHAR_T
   4241   template<typename _Out> requires output_iterator<_Out, const wchar_t&>
   4242     [[__gnu__::__always_inline__]]
   4243     inline _Out
   4244     vformat_to(_Out __out, const locale& __loc, wstring_view __fmt,
   4245 	       wformat_args __args)
   4246     {
   4247       return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
   4248     }
   4249 #endif
   4250 
   4251   [[nodiscard]]
   4252   inline string
   4253   vformat(string_view __fmt, format_args __args)
   4254   {
   4255     __format::_Str_sink<char> __buf;
   4256     std::vformat_to(__buf.out(), __fmt, __args);
   4257     return std::move(__buf).get();
   4258   }
   4259 
   4260 #ifdef _GLIBCXX_USE_WCHAR_T
   4261   [[nodiscard]]
   4262   inline wstring
   4263   vformat(wstring_view __fmt, wformat_args __args)
   4264   {
   4265     __format::_Str_sink<wchar_t> __buf;
   4266     std::vformat_to(__buf.out(), __fmt, __args);
   4267     return std::move(__buf).get();
   4268   }
   4269 #endif
   4270 
   4271   [[nodiscard]]
   4272   inline string
   4273   vformat(const locale& __loc, string_view __fmt, format_args __args)
   4274   {
   4275     __format::_Str_sink<char> __buf;
   4276     std::vformat_to(__buf.out(), __loc, __fmt, __args);
   4277     return std::move(__buf).get();
   4278   }
   4279 
   4280 #ifdef _GLIBCXX_USE_WCHAR_T
   4281   [[nodiscard]]
   4282   inline wstring
   4283   vformat(const locale& __loc, wstring_view __fmt, wformat_args __args)
   4284   {
   4285     __format::_Str_sink<wchar_t> __buf;
   4286     std::vformat_to(__buf.out(), __loc, __fmt, __args);
   4287     return std::move(__buf).get();
   4288   }
   4289 #endif
   4290 
   4291   template<typename... _Args>
   4292     [[nodiscard]]
   4293     inline string
   4294     format(format_string<_Args...> __fmt, _Args&&... __args)
   4295     { return std::vformat(__fmt.get(), std::make_format_args(__args...)); }
   4296 
   4297 #ifdef _GLIBCXX_USE_WCHAR_T
   4298   template<typename... _Args>
   4299     [[nodiscard]]
   4300     inline wstring
   4301     format(wformat_string<_Args...> __fmt, _Args&&... __args)
   4302     { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); }
   4303 #endif
   4304 
   4305   template<typename... _Args>
   4306     [[nodiscard]]
   4307     inline string
   4308     format(const locale& __loc, format_string<_Args...> __fmt,
   4309 	   _Args&&... __args)
   4310     {
   4311       return std::vformat(__loc, __fmt.get(),
   4312 			  std::make_format_args(__args...));
   4313     }
   4314 
   4315 #ifdef _GLIBCXX_USE_WCHAR_T
   4316   template<typename... _Args>
   4317     [[nodiscard]]
   4318     inline wstring
   4319     format(const locale& __loc, wformat_string<_Args...> __fmt,
   4320 	   _Args&&... __args)
   4321     {
   4322       return std::vformat(__loc, __fmt.get(),
   4323 			  std::make_wformat_args(__args...));
   4324     }
   4325 #endif
   4326 
   4327   template<typename _Out, typename... _Args>
   4328     requires output_iterator<_Out, const char&>
   4329     inline _Out
   4330     format_to(_Out __out, format_string<_Args...> __fmt, _Args&&... __args)
   4331     {
   4332       return std::vformat_to(std::move(__out), __fmt.get(),
   4333 			     std::make_format_args(__args...));
   4334     }
   4335 
   4336 #ifdef _GLIBCXX_USE_WCHAR_T
   4337   template<typename _Out, typename... _Args>
   4338     requires output_iterator<_Out, const wchar_t&>
   4339     inline _Out
   4340     format_to(_Out __out, wformat_string<_Args...> __fmt, _Args&&... __args)
   4341     {
   4342       return std::vformat_to(std::move(__out), __fmt.get(),
   4343 			     std::make_wformat_args(__args...));
   4344     }
   4345 #endif
   4346 
   4347   template<typename _Out, typename... _Args>
   4348     requires output_iterator<_Out, const char&>
   4349     inline _Out
   4350     format_to(_Out __out, const locale& __loc, format_string<_Args...> __fmt,
   4351 	      _Args&&... __args)
   4352     {
   4353       return std::vformat_to(std::move(__out), __loc, __fmt.get(),
   4354 			     std::make_format_args(__args...));
   4355     }
   4356 
   4357 #ifdef _GLIBCXX_USE_WCHAR_T
   4358   template<typename _Out, typename... _Args>
   4359     requires output_iterator<_Out, const wchar_t&>
   4360     inline _Out
   4361     format_to(_Out __out, const locale& __loc, wformat_string<_Args...> __fmt,
   4362 	      _Args&&... __args)
   4363     {
   4364       return std::vformat_to(std::move(__out), __loc, __fmt.get(),
   4365 			     std::make_wformat_args(__args...));
   4366     }
   4367 #endif
   4368 
   4369   template<typename _Out, typename... _Args>
   4370     requires output_iterator<_Out, const char&>
   4371     inline format_to_n_result<_Out>
   4372     format_to_n(_Out __out, iter_difference_t<_Out> __n,
   4373 		format_string<_Args...> __fmt, _Args&&... __args)
   4374     {
   4375       __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
   4376       std::vformat_to(__sink.out(), __fmt.get(),
   4377 		      std::make_format_args(__args...));
   4378       return std::move(__sink)._M_finish();
   4379     }
   4380 
   4381 #ifdef _GLIBCXX_USE_WCHAR_T
   4382   template<typename _Out, typename... _Args>
   4383     requires output_iterator<_Out, const wchar_t&>
   4384     inline format_to_n_result<_Out>
   4385     format_to_n(_Out __out, iter_difference_t<_Out> __n,
   4386 		wformat_string<_Args...> __fmt, _Args&&... __args)
   4387     {
   4388       __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
   4389       std::vformat_to(__sink.out(), __fmt.get(),
   4390 		      std::make_wformat_args(__args...));
   4391       return std::move(__sink)._M_finish();
   4392     }
   4393 #endif
   4394 
   4395   template<typename _Out, typename... _Args>
   4396     requires output_iterator<_Out, const char&>
   4397     inline format_to_n_result<_Out>
   4398     format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
   4399 		format_string<_Args...> __fmt, _Args&&... __args)
   4400     {
   4401       __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
   4402       std::vformat_to(__sink.out(), __loc, __fmt.get(),
   4403 		      std::make_format_args(__args...));
   4404       return std::move(__sink)._M_finish();
   4405     }
   4406 
   4407 #ifdef _GLIBCXX_USE_WCHAR_T
   4408   template<typename _Out, typename... _Args>
   4409     requires output_iterator<_Out, const wchar_t&>
   4410     inline format_to_n_result<_Out>
   4411     format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
   4412 		wformat_string<_Args...> __fmt, _Args&&... __args)
   4413     {
   4414       __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
   4415       std::vformat_to(__sink.out(), __loc, __fmt.get(),
   4416 		      std::make_wformat_args(__args...));
   4417       return std::move(__sink)._M_finish();
   4418     }
   4419 #endif
   4420 
   4421 /// @cond undocumented
   4422 namespace __format
   4423 {
   4424 #if 1
   4425   template<typename _CharT>
   4426     class _Counting_sink final : public _Iter_sink<_CharT, _CharT*>
   4427     {
   4428     public:
   4429       _Counting_sink() : _Iter_sink<_CharT, _CharT*>(nullptr, 0) { }
   4430 
   4431       [[__gnu__::__always_inline__]]
   4432       size_t
   4433       count() const
   4434       { return this->_M_count + this->_M_used().size(); }
   4435     };
   4436 #else
   4437   template<typename _CharT>
   4438     class _Counting_sink : public _Buf_sink<_CharT>
   4439     {
   4440       size_t _M_count = 0;
   4441 
   4442       void
   4443       _M_overflow() override
   4444       {
   4445 	if (!std::is_constant_evaluated())
   4446 	  _M_count += this->_M_used().size();
   4447 	this->_M_rewind();
   4448       }
   4449 
   4450     public:
   4451       _Counting_sink() = default;
   4452 
   4453       [[__gnu__::__always_inline__]]
   4454       size_t
   4455       count() noexcept
   4456       {
   4457 	_Counting_sink::_M_overflow();
   4458 	return _M_count;
   4459       }
   4460     };
   4461 #endif
   4462 } // namespace __format
   4463 /// @endcond
   4464 
   4465   template<typename... _Args>
   4466     [[nodiscard]]
   4467     inline size_t
   4468     formatted_size(format_string<_Args...> __fmt, _Args&&... __args)
   4469     {
   4470       __format::_Counting_sink<char> __buf;
   4471       std::vformat_to(__buf.out(), __fmt.get(),
   4472 		      std::make_format_args(__args...));
   4473       return __buf.count();
   4474     }
   4475 
   4476 #ifdef _GLIBCXX_USE_WCHAR_T
   4477   template<typename... _Args>
   4478     [[nodiscard]]
   4479     inline size_t
   4480     formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args)
   4481     {
   4482       __format::_Counting_sink<wchar_t> __buf;
   4483       std::vformat_to(__buf.out(), __fmt.get(),
   4484 		      std::make_wformat_args(__args...));
   4485       return __buf.count();
   4486     }
   4487 #endif
   4488 
   4489   template<typename... _Args>
   4490     [[nodiscard]]
   4491     inline size_t
   4492     formatted_size(const locale& __loc, format_string<_Args...> __fmt,
   4493 		   _Args&&... __args)
   4494     {
   4495       __format::_Counting_sink<char> __buf;
   4496       std::vformat_to(__buf.out(), __loc, __fmt.get(),
   4497 		      std::make_format_args(__args...));
   4498       return __buf.count();
   4499     }
   4500 
   4501 #ifdef _GLIBCXX_USE_WCHAR_T
   4502   template<typename... _Args>
   4503     [[nodiscard]]
   4504     inline size_t
   4505     formatted_size(const locale& __loc, wformat_string<_Args...> __fmt,
   4506 		   _Args&&... __args)
   4507     {
   4508       __format::_Counting_sink<wchar_t> __buf;
   4509       std::vformat_to(__buf.out(), __loc, __fmt.get(),
   4510 		      std::make_wformat_args(__args...));
   4511       return __buf.count();
   4512     }
   4513 #endif
   4514 
   4515 #if __cpp_lib_format_ranges
   4516   // [format.range], formatting of ranges
   4517   // [format.range.fmtkind], variable template format_kind
   4518   enum class range_format {
   4519     disabled,
   4520     map,
   4521     set,
   4522     sequence,
   4523     string,
   4524     debug_string
   4525   };
   4526 
   4527   /// @cond undocumented
   4528   template<typename _Rg>
   4529     constexpr auto format_kind = not defined(format_kind<_Rg>);
   4530 
   4531   template<typename _Tp>
   4532     consteval range_format
   4533     __fmt_kind()
   4534     {
   4535       using _Ref = ranges::range_reference_t<_Tp>;
   4536       if constexpr (is_same_v<remove_cvref_t<_Ref>, _Tp>)
   4537 	return range_format::disabled;
   4538       else if constexpr (requires { typename _Tp::key_type; })
   4539 	{
   4540 	  if constexpr (requires { typename _Tp::mapped_type; })
   4541 	    {
   4542 	      using _Up = remove_cvref_t<_Ref>;
   4543 	      if constexpr (__is_pair<_Up>)
   4544 		return range_format::map;
   4545 	      else if constexpr (__is_specialization_of<_Up, tuple>)
   4546 		if constexpr (tuple_size_v<_Up> == 2)
   4547 		  return range_format::map;
   4548 	    }
   4549 	  return range_format::set;
   4550 	}
   4551       else
   4552 	return range_format::sequence;
   4553     }
   4554   /// @endcond
   4555 
   4556   /// A constant determining how a range should be formatted.
   4557   template<ranges::input_range _Rg> requires same_as<_Rg, remove_cvref_t<_Rg>>
   4558     constexpr range_format format_kind<_Rg> = __fmt_kind<_Rg>();
   4559 
   4560   // [format.range.formatter], class template range_formatter
   4561   template<typename _Tp, typename _CharT = char>
   4562     requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
   4563     class range_formatter; // TODO
   4564 
   4565 /// @cond undocumented
   4566 namespace __format
   4567 {
   4568   // [format.range.fmtdef], class template range-default-formatter
   4569   template<range_format _Kind, ranges::input_range _Rg, typename _CharT>
   4570     struct __range_default_formatter; // TODO
   4571 } // namespace __format
   4572 /// @endcond
   4573 
   4574   // [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr],
   4575   // specializations for maps, sets, and strings
   4576   template<ranges::input_range _Rg, typename _CharT>
   4577     requires (format_kind<_Rg> != range_format::disabled)
   4578       && formattable<ranges::range_reference_t<_Rg>, _CharT>
   4579     struct formatter<_Rg, _CharT>
   4580     : __format::__range_default_formatter<format_kind<_Rg>, _Rg, _CharT>
   4581     { };
   4582 #endif // C++23 formatting ranges
   4583 
   4584 _GLIBCXX_END_NAMESPACE_VERSION
   4585 } // namespace std
   4586 #endif // __cpp_lib_format
   4587 #endif // _GLIBCXX_FORMAT
   4588