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