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