libstdc++: Only declare feature test macros in standard headers
[official-gcc.git] / libstdc++-v3 / include / std / format
blob8ec1c8a0b9a75548d3900e2c4258e5fb698b7778
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 /// @cond undocumented
2446 namespace __format
2448   template<typename _CharT>
2449     class _Sink_iter
2450     {
2451       _Sink<_CharT>* _M_sink = nullptr;
2453     public:
2454       using iterator_category = output_iterator_tag;
2455       using value_type = void;
2456       using difference_type = ptrdiff_t;
2457       using pointer = void;
2458       using reference = void;
2460       _Sink_iter() = default;
2461       _Sink_iter(const _Sink_iter&) = default;
2462       _Sink_iter& operator=(const _Sink_iter&) = default;
2464       [[__gnu__::__always_inline__]]
2465       explicit constexpr
2466       _Sink_iter(_Sink<_CharT>& __sink) : _M_sink(std::addressof(__sink)) { }
2468       [[__gnu__::__always_inline__]]
2469       constexpr _Sink_iter&
2470       operator=(_CharT __c)
2471       {
2472         _M_sink->_M_write(__c);
2473         return *this;
2474       }
2476       [[__gnu__::__always_inline__]]
2477       constexpr _Sink_iter&
2478       operator=(basic_string_view<_CharT> __s)
2479       {
2480         _M_sink->_M_write(__s);
2481         return *this;
2482       }
2484       [[__gnu__::__always_inline__]]
2485       constexpr _Sink_iter&
2486       operator*() { return *this; }
2488       [[__gnu__::__always_inline__]]
2489       constexpr _Sink_iter&
2490       operator++() { return *this; }
2492       [[__gnu__::__always_inline__]]
2493       constexpr _Sink_iter
2494       operator++(int) { return *this; }
2495     };
2497   // Abstract base class for type-erased character sinks.
2498   // All formatting and output is done via this type's iterator,
2499   // to reduce the number of different template instantiations.
2500   template<typename _CharT>
2501     class _Sink
2502     {
2503       friend class _Sink_iter<_CharT>;
2505       span<_CharT> _M_span;
2506       typename span<_CharT>::iterator _M_next;
2508       // Called when the span is full, to make more space available.
2509       // Precondition: _M_next != _M_span.begin()
2510       // Postcondition: _M_next != _M_span.end()
2511       virtual void _M_overflow() = 0;
2513     protected:
2514       // Precondition: __span.size() != 0
2515       [[__gnu__::__always_inline__]]
2516       explicit constexpr
2517       _Sink(span<_CharT> __span) noexcept
2518       : _M_span(__span), _M_next(__span.begin())
2519       { }
2521       // The portion of the span that has been written to.
2522       [[__gnu__::__always_inline__]]
2523       span<_CharT>
2524       _M_used() const noexcept
2525       { return _M_span.first(_M_next - _M_span.begin()); }
2527       // The portion of the span that has not been written to.
2528       [[__gnu__::__always_inline__]]
2529       constexpr span<_CharT>
2530       _M_unused() const noexcept
2531       { return _M_span.subspan(_M_next - _M_span.begin()); }
2533       // Use the start of the span as the next write position.
2534       [[__gnu__::__always_inline__]]
2535       constexpr void
2536       _M_rewind() noexcept
2537       { _M_next = _M_span.begin(); }
2539       // Replace the current output range.
2540       void
2541       _M_reset(span<_CharT> __s, size_t __pos = 0) noexcept
2542       {
2543         _M_span = __s;
2544         _M_next = __s.begin() + __pos;
2545       }
2547       // Called by the iterator for *it++ = c
2548       constexpr void
2549       _M_write(_CharT __c)
2550       {
2551         *_M_next++ = __c;
2552         if (_M_next - _M_span.begin() == std::ssize(_M_span)) [[unlikely]]
2553           _M_overflow();
2554       }
2556       constexpr void
2557       _M_write(basic_string_view<_CharT> __s)
2558       {
2559         span __to = _M_unused();
2560         while (__to.size() <= __s.size())
2561           {
2562             __s.copy(__to.data(), __to.size());
2563             _M_next += __to.size();
2564             __s.remove_prefix(__to.size());
2565             _M_overflow();
2566             __to = _M_unused();
2567           }
2568         if (__s.size())
2569           {
2570             __s.copy(__to.data(), __s.size());
2571             _M_next += __s.size();
2572           }
2573       }
2575     public:
2576       _Sink(const _Sink&) = delete;
2577       _Sink& operator=(const _Sink&) = delete;
2579       [[__gnu__::__always_inline__]]
2580       constexpr _Sink_iter<_CharT>
2581       out() noexcept
2582       { return _Sink_iter<_CharT>(*this); }
2583     };
2585   // A sink with an internal buffer. This is used to implement concrete sinks.
2586   template<typename _CharT>
2587     class _Buf_sink : public _Sink<_CharT>
2588     {
2589     protected:
2590       _CharT _M_buf[32 * sizeof(void*) / sizeof(_CharT)];
2592       [[__gnu__::__always_inline__]]
2593       constexpr
2594       _Buf_sink() noexcept
2595       : _Sink<_CharT>(_M_buf)
2596       { }
2597     };
2599   // A sink that fills a sequence (e.g. std::string, std::vector, std::deque).
2600   // Writes to a buffer then appends that to the sequence when it fills up.
2601   template<typename _Seq>
2602     class _Seq_sink final : public _Buf_sink<typename _Seq::value_type>
2603     {
2604       using _CharT = typename _Seq::value_type;
2606       _Seq _M_seq;
2608       // Transfer buffer contents to the sequence, so buffer can be refilled.
2609       void
2610       _M_overflow() override
2611       {
2612         auto __s = this->_M_used();
2613         if (__s.empty())
2614           return;
2615         if constexpr (__is_specialization_of<_Seq, basic_string>)
2616           _M_seq.append(__s.data(), __s.size());
2617         else
2618           _M_seq.insert(_M_seq.end(), __s.begin(), __s.end());
2619         this->_M_rewind();
2620       }
2622     public:
2623       // TODO: for SSO string, use SSO buffer as initial span, then switch
2624       // to _M_buf if it overflows? Or even do that for all unused capacity?
2626       [[__gnu__::__always_inline__]]
2627       _Seq_sink() noexcept(is_nothrow_default_constructible_v<_Seq>)
2628       { }
2630       _Seq_sink(_Seq&& __s) noexcept(is_nothrow_move_constructible_v<_Seq>)
2631       : _M_seq(std::move(__s))
2632       { }
2634       using _Sink<_CharT>::out;
2636       _Seq
2637       get() &&
2638       {
2639         if (this->_M_used().size() != 0)
2640           _Seq_sink::_M_overflow();
2641         return std::move(_M_seq);
2642       }
2643     };
2645   template<typename _CharT, typename _Alloc = allocator<_CharT>>
2646     using _Str_sink
2647       = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>;
2649   // template<typename _CharT, typename _Alloc = allocator<_CharT>>
2650     // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>;
2652   // A sink that writes to an output iterator.
2653   // Writes to a fixed-size buffer and then flushes to the output iterator
2654   // when the buffer fills up.
2655   template<typename _CharT, typename _OutIter>
2656     class _Iter_sink : public _Buf_sink<_CharT>
2657     {
2658       _OutIter _M_out;
2659       iter_difference_t<_OutIter> _M_max;
2661     protected:
2662       size_t _M_count = 0;
2664       void
2665       _M_overflow() override
2666       {
2667         auto __s = this->_M_used();
2668         if (_M_max < 0) // No maximum.
2669           _M_out = ranges::copy(__s, std::move(_M_out)).out;
2670         else if (_M_count < static_cast<size_t>(_M_max))
2671           {
2672             auto __max = _M_max - _M_count;
2673             span<_CharT> __first;
2674             if (__max < __s.size())
2675               __first = __s.first(static_cast<size_t>(__max));
2676             else
2677               __first = __s;
2678             _M_out = ranges::copy(__first, std::move(_M_out)).out;
2679           }
2680         this->_M_rewind();
2681         _M_count += __s.size();
2682       }
2684     public:
2685       [[__gnu__::__always_inline__]]
2686       explicit
2687       _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __max = -1)
2688       : _M_out(std::move(__out)), _M_max(__max)
2689       { }
2691       using _Sink<_CharT>::out;
2693       format_to_n_result<_OutIter>
2694       _M_finish() &&
2695       {
2696         if (this->_M_used().size() != 0)
2697           _Iter_sink::_M_overflow();
2698         iter_difference_t<_OutIter> __count(_M_count);
2699         return { std::move(_M_out), __count };
2700       }
2701     };
2703   // Partial specialization for contiguous iterators.
2704   // No buffer is used, characters are written straight to the iterator.
2705   // We do not know the size of the output range, so the span size just grows
2706   // as needed. The end of the span might be an invalid pointer outside the
2707   // valid range, but we never actually call _M_span.end(). This class does
2708   // not introduce any invalid pointer arithmetic or overflows that would not
2709   // have happened anyway.
2710   template<typename _CharT, contiguous_iterator _OutIter>
2711     requires same_as<iter_value_t<_OutIter>, _CharT>
2712     class _Iter_sink<_CharT, _OutIter> : public _Sink<_CharT>
2713     {
2714       using uint64_t = __UINTPTR_TYPE__;
2715       _OutIter _M_first;
2716       iter_difference_t<_OutIter> _M_max = -1;
2717     protected:
2718       size_t _M_count = 0;
2719     private:
2720       _CharT _M_buf[64]; // Write here after outputting _M_max characters.
2722     protected:
2723       void
2724       _M_overflow() override
2725       {
2726         if (this->_M_unused().size() != 0)
2727           return; // No need to switch to internal buffer yet.
2729         auto __s = this->_M_used();
2731         if (_M_max >= 0)
2732           {
2733             _M_count += __s.size();
2734             // Span was already sized for the maximum character count,
2735             // if it overflows then any further output must go to the
2736             // internal buffer, to be discarded.
2737             this->_M_reset(this->_M_buf);
2738           }
2739         else
2740           {
2741             // No maximum character count. Just extend the span to allow
2742             // writing more characters to it.
2743             this->_M_reset({__s.data(), __s.size() + 1024}, __s.size());
2744           }
2745       }
2747     private:
2748       static span<_CharT>
2749       _S_make_span(_CharT* __ptr, iter_difference_t<_OutIter> __n,
2750                    span<_CharT> __buf) noexcept
2751       {
2752         if (__n == 0)
2753           return __buf; // Only write to the internal buffer.
2755         if (__n > 0)
2756           {
2757             if constexpr (!is_integral_v<iter_difference_t<_OutIter>>
2758                             || sizeof(__n) > sizeof(size_t))
2759               {
2760                 // __int128 or __detail::__max_diff_type
2761                 auto __m = iter_difference_t<_OutIter>((size_t)-1);
2762                 if (__n > __m)
2763                   __n = __m;
2764               }
2765             return {__ptr, (size_t)__n};
2766           }
2768 #if __has_builtin(__builtin_dynamic_object_size)
2769         if (size_t __bytes = __builtin_dynamic_object_size(__ptr, 2))
2770           return {__ptr, __bytes / sizeof(_CharT)};
2771 #endif
2772         // Avoid forming a pointer to a different memory page.
2773         uint64_t __off = reinterpret_cast<uint64_t>(__ptr) % 1024;
2774         __n = (1024 - __off) / sizeof(_CharT);
2775         if (__n > 0) [[likely]]
2776         return {__ptr, static_cast<size_t>(__n)};
2777         else // Misaligned/packed buffer of wchar_t?
2778           return {__ptr, 1};
2779       }
2781     public:
2782       explicit
2783       _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __n = -1) noexcept
2784       : _Sink<_CharT>(_S_make_span(std::to_address(__out), __n, _M_buf)),
2785         _M_first(__out), _M_max(__n)
2786       { }
2788       format_to_n_result<_OutIter>
2789       _M_finish() &&
2790       {
2791         auto __s = this->_M_used();
2792         if (__s.data() == _M_buf)
2793           {
2794             // Switched to internal buffer, so must have written _M_max.
2795             iter_difference_t<_OutIter> __count(_M_count + __s.size());
2796             return { _M_first + _M_max, __count };
2797           }
2798         else // Not using internal buffer yet
2799           {
2800             iter_difference_t<_OutIter> __count(__s.size());
2801             return { _M_first + __count, __count };
2802           }
2803       }
2804     };
2806   enum _Arg_t : unsigned char {
2807     _Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull,
2808     _Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr, _Arg_handle,
2809     _Arg_i128, _Arg_u128,
2810     _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, // These are unused.
2811 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
2812     _Arg_next_value_,
2813     _Arg_f128 = _Arg_ldbl,
2814     _Arg_ibm128 = _Arg_next_value_,
2815 #else
2816     _Arg_f128,
2817 #endif
2818     _Arg_max_
2819   };
2821   template<typename _Context>
2822     struct _Arg_value
2823     {
2824       using _CharT = typename _Context::char_type;
2826       struct _HandleBase
2827       {
2828         const void* _M_ptr;
2829         void (*_M_func)();
2830       };
2832       union
2833       {
2834         monostate _M_none;
2835         bool _M_bool;
2836         _CharT _M_c;
2837         int _M_i;
2838         unsigned _M_u;
2839         long long _M_ll;
2840         unsigned long long _M_ull;
2841         float _M_flt;
2842         double _M_dbl;
2843 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // No long double if it's ambiguous.
2844         long double _M_ldbl;
2845 #endif
2846         const _CharT* _M_str;
2847         basic_string_view<_CharT> _M_sv;
2848         const void* _M_ptr;
2849         _HandleBase _M_handle;
2850 #ifdef __SIZEOF_INT128__
2851         __int128 _M_i128;
2852         unsigned __int128 _M_u128;
2853 #endif
2854 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
2855         __ieee128 _M_f128;
2856         __ibm128  _M_ibm128;
2857 #elif _GLIBCXX_FORMAT_F128 == 2
2858         __float128_t _M_f128;
2859 #endif
2860       };
2862       [[__gnu__::__always_inline__]]
2863       _Arg_value() : _M_none() { }
2865 #if 0
2866       template<typename _Tp>
2867         _Arg_value(in_place_type_t<_Tp>, _Tp __val)
2868         { _S_get<_Tp>() = __val; }
2869 #endif
2871       template<typename _Tp, typename _Self>
2872         [[__gnu__::__always_inline__]]
2873         static auto&
2874         _S_get(_Self& __u) noexcept
2875         {
2876           if constexpr (is_same_v<_Tp, bool>)
2877             return __u._M_bool;
2878           else if constexpr (is_same_v<_Tp, _CharT>)
2879             return __u._M_c;
2880           else if constexpr (is_same_v<_Tp, int>)
2881             return __u._M_i;
2882           else if constexpr (is_same_v<_Tp, unsigned>)
2883             return __u._M_u;
2884           else if constexpr (is_same_v<_Tp, long long>)
2885             return __u._M_ll;
2886           else if constexpr (is_same_v<_Tp, unsigned long long>)
2887             return __u._M_ull;
2888           else if constexpr (is_same_v<_Tp, float>)
2889             return __u._M_flt;
2890           else if constexpr (is_same_v<_Tp, double>)
2891             return __u._M_dbl;
2892 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
2893           else if constexpr (is_same_v<_Tp, long double>)
2894             return __u._M_ldbl;
2895 #else
2896           else if constexpr (is_same_v<_Tp, __ieee128>)
2897             return __u._M_f128;
2898           else if constexpr (is_same_v<_Tp, __ibm128>)
2899             return __u._M_ibm128;
2900 #endif
2901           else if constexpr (is_same_v<_Tp, const _CharT*>)
2902             return __u._M_str;
2903           else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
2904             return __u._M_sv;
2905           else if constexpr (is_same_v<_Tp, const void*>)
2906             return __u._M_ptr;
2907 #ifdef __SIZEOF_INT128__
2908           else if constexpr (is_same_v<_Tp, __int128>)
2909             return __u._M_i128;
2910           else if constexpr (is_same_v<_Tp, unsigned __int128>)
2911             return __u._M_u128;
2912 #endif
2913 #if _GLIBCXX_FORMAT_F128 == 2
2914           else if constexpr (is_same_v<_Tp, __float128_t>)
2915             return __u._M_f128;
2916 #endif
2917           else if constexpr (derived_from<_Tp, _HandleBase>)
2918             return static_cast<_Tp&>(__u._M_handle);
2919           // Otherwise, ill-formed.
2920         }
2922       template<typename _Tp>
2923         [[__gnu__::__always_inline__]]
2924         auto&
2925         _M_get() noexcept
2926         { return _S_get<_Tp>(*this); }
2928       template<typename _Tp>
2929         [[__gnu__::__always_inline__]]
2930         const auto&
2931         _M_get() const noexcept
2932         { return _S_get<_Tp>(*this); }
2934       template<typename _Tp>
2935         [[__gnu__::__always_inline__]]
2936         void
2937         _M_set(_Tp __v) noexcept
2938         {
2939           if constexpr (derived_from<_Tp, _HandleBase>)
2940             std::construct_at(&_M_handle, __v);
2941           else
2942             _S_get<_Tp>(*this) = __v;
2943         }
2944       };
2946   // [format.arg.store], class template format-arg-store
2947   template<typename _Context, typename... _Args>
2948     class _Arg_store;
2950 } // namespace __format
2951 /// @endcond
2953   template<typename _Context>
2954     class basic_format_arg
2955     {
2956       using _CharT = typename _Context::char_type;
2958       template<typename _Tp>
2959         static constexpr bool __formattable
2960           = __format::__formattable_with<_Tp, _Context>;
2962     public:
2963       class handle : public __format::_Arg_value<_Context>::_HandleBase
2964       {
2965         using _Base = typename __format::_Arg_value<_Context>::_HandleBase;
2967         // Format as const if possible, to reduce instantiations.
2968         template<typename _Tp>
2969           using __maybe_const_t
2970             = __conditional_t<__format::__formattable_with<_Tp, _Context>,
2971                               const _Tp, _Tp>;
2973         template<typename _Tq>
2974           static void
2975           _S_format(basic_format_parse_context<_CharT>& __parse_ctx,
2976                     _Context& __format_ctx, const void* __ptr)
2977           {
2978             using _Td = remove_const_t<_Tq>;
2979             typename _Context::template formatter_type<_Td> __f;
2980             __parse_ctx.advance_to(__f.parse(__parse_ctx));
2981             _Tq& __val = *const_cast<_Tq*>(static_cast<const _Td*>(__ptr));
2982             __format_ctx.advance_to(__f.format(__val, __format_ctx));
2983           }
2985         template<typename _Tp>
2986           explicit
2987           handle(_Tp& __val) noexcept
2988           {
2989             if constexpr (!__format::__formattable_with<const _Tp, _Context>)
2990               static_assert(!is_const_v<_Tp>, "std::format argument must be "
2991                                               "non-const for this type");
2993             this->_M_ptr = __builtin_addressof(__val);
2994             auto __func = _S_format<__maybe_const_t<_Tp>>;
2995             this->_M_func = reinterpret_cast<void(*)()>(__func);
2996           }
2998         friend class basic_format_arg<_Context>;
3000       public:
3001         handle(const handle&) = default;
3002         handle& operator=(const handle&) = default;
3004         [[__gnu__::__always_inline__]]
3005         void
3006         format(basic_format_parse_context<_CharT>& __pc, _Context& __fc) const
3007         {
3008           using _Func = void(*)(basic_format_parse_context<_CharT>&,
3009                                 _Context&, const void*);
3010           auto __f = reinterpret_cast<_Func>(this->_M_func);
3011           __f(__pc, __fc, this->_M_ptr);
3012         }
3013       };
3015       [[__gnu__::__always_inline__]]
3016       basic_format_arg() noexcept : _M_type(__format::_Arg_none) { }
3018       [[nodiscard,__gnu__::__always_inline__]]
3019       explicit operator bool() const noexcept
3020       { return _M_type != __format::_Arg_none; }
3022     private:
3023       template<typename _Ctx>
3024         friend class basic_format_args;
3026       template<typename _Ctx, typename... _Args>
3027         friend class __format::_Arg_store;
3029       static_assert(is_trivially_copyable_v<__format::_Arg_value<_Context>>);
3031       __format::_Arg_value<_Context> _M_val;
3032       __format::_Arg_t _M_type;
3034       // Transform incoming argument type to the type stored in _Arg_value.
3035       // e.g. short -> int, std::string -> std::string_view,
3036       // char[3] -> const char*.
3037       template<typename _Tp>
3038         static consteval auto
3039         _S_to_arg_type()
3040         {
3041           using _Td = remove_const_t<_Tp>;
3042           if constexpr (is_same_v<_Td, bool>)
3043             return type_identity<bool>();
3044           else if constexpr (is_same_v<_Td, _CharT>)
3045             return type_identity<_CharT>();
3046           else if constexpr (is_same_v<_Td, char> && is_same_v<_CharT, wchar_t>)
3047             return type_identity<_CharT>();
3048 #ifdef __SIZEOF_INT128__ // Check before signed/unsigned integer
3049           else if constexpr (is_same_v<_Td, __int128>)
3050             return type_identity<__int128>();
3051           else if constexpr (is_same_v<_Td, unsigned __int128>)
3052             return type_identity<unsigned __int128>();
3053 #endif
3054           else if constexpr (__is_signed_integer<_Td>::value)
3055             {
3056               if constexpr (sizeof(_Td) <= sizeof(int))
3057                 return type_identity<int>();
3058               else if constexpr (sizeof(_Td) <= sizeof(long long))
3059                 return type_identity<long long>();
3060             }
3061           else if constexpr (__is_unsigned_integer<_Td>::value)
3062             {
3063               if constexpr (sizeof(_Td) <= sizeof(unsigned))
3064                 return type_identity<unsigned>();
3065               else if constexpr (sizeof(_Td) <= sizeof(unsigned long long))
3066                 return type_identity<unsigned long long>();
3067             }
3068           else if constexpr (is_same_v<_Td, float>)
3069             return type_identity<float>();
3070           else if constexpr (is_same_v<_Td, double>)
3071             return type_identity<double>();
3072 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3073           else if constexpr (is_same_v<_Td, long double>)
3074             return type_identity<long double>();
3075 #else
3076           else if constexpr (is_same_v<_Td, __ibm128>)
3077             return type_identity<__ibm128>();
3078           else if constexpr (is_same_v<_Td, __ieee128>)
3079             return type_identity<__ieee128>();
3080 #endif
3082 #if defined(__FLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
3083           else if constexpr (is_same_v<_Td, _Float16>)
3084             return type_identity<float>();
3085 #endif
3087 #if defined(__BFLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
3088           else if constexpr (is_same_v<_Td, decltype(0.0bf16)>)
3089             return type_identity<float>();
3090 #endif
3092 #ifdef __FLT32_DIG__
3093           else if constexpr (is_same_v<_Td, _Float32>)
3094 # ifdef _GLIBCXX_FLOAT_IS_IEEE_BINARY32
3095             return type_identity<float>();
3096 # else
3097             return type_identity<_Float32>();
3098 # endif
3099 #endif
3100 #ifdef __FLT64_DIG__
3101           else if constexpr (is_same_v<_Td, _Float64>)
3102 # ifdef _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
3103             return type_identity<double>();
3104 # else
3105             return type_identity<_Float64>();
3106 # endif
3107 #endif
3108 #if _GLIBCXX_FORMAT_F128
3109 # if __FLT128_DIG__
3110           else if constexpr (is_same_v<_Td, _Float128>)
3111             return type_identity<__format::__float128_t>();
3112 # endif
3113 # if __SIZEOF_FLOAT128__
3114           else if constexpr (is_same_v<_Td, __float128>)
3115             return type_identity<__format::__float128_t>();
3116 # endif
3117 #endif
3118           else if constexpr (__is_specialization_of<_Td, basic_string_view>)
3119             return type_identity<basic_string_view<_CharT>>();
3120           else if constexpr (__is_specialization_of<_Td, basic_string>)
3121             return type_identity<basic_string_view<_CharT>>();
3122           else if constexpr (is_same_v<decay_t<_Td>, const _CharT*>)
3123             return type_identity<const _CharT*>();
3124           else if constexpr (is_same_v<decay_t<_Td>, _CharT*>)
3125             return type_identity<const _CharT*>();
3126           else if constexpr (is_void_v<remove_pointer_t<_Td>>)
3127             return type_identity<const void*>();
3128           else if constexpr (is_same_v<_Td, nullptr_t>)
3129             return type_identity<const void*>();
3130           else
3131             return type_identity<handle>();
3132         }
3134       // Transform a formattable type to the appropriate storage type.
3135       template<typename _Tp>
3136         using _Normalize = typename decltype(_S_to_arg_type<_Tp>())::type;
3138       // Get the _Arg_t value corresponding to a normalized type.
3139       template<typename _Tp>
3140         static consteval __format::_Arg_t
3141         _S_to_enum()
3142         {
3143           using namespace __format;
3144           if constexpr (is_same_v<_Tp, bool>)
3145             return _Arg_bool;
3146           else if constexpr (is_same_v<_Tp, _CharT>)
3147             return _Arg_c;
3148           else if constexpr (is_same_v<_Tp, int>)
3149             return _Arg_i;
3150           else if constexpr (is_same_v<_Tp, unsigned>)
3151             return _Arg_u;
3152           else if constexpr (is_same_v<_Tp, long long>)
3153             return _Arg_ll;
3154           else if constexpr (is_same_v<_Tp, unsigned long long>)
3155             return _Arg_ull;
3156           else if constexpr (is_same_v<_Tp, float>)
3157             return _Arg_flt;
3158           else if constexpr (is_same_v<_Tp, double>)
3159             return _Arg_dbl;
3160 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3161           else if constexpr (is_same_v<_Tp, long double>)
3162             return _Arg_ldbl;
3163 #else
3164           // Don't use _Arg_ldbl for this target, it's ambiguous.
3165           else if constexpr (is_same_v<_Tp, __ibm128>)
3166             return _Arg_ibm128;
3167           else if constexpr (is_same_v<_Tp, __ieee128>)
3168             return _Arg_f128;
3169 #endif
3170           else if constexpr (is_same_v<_Tp, const _CharT*>)
3171             return _Arg_str;
3172           else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
3173             return _Arg_sv;
3174           else if constexpr (is_same_v<_Tp, const void*>)
3175             return _Arg_ptr;
3176 #ifdef __SIZEOF_INT128__
3177           else if constexpr (is_same_v<_Tp, __int128>)
3178             return _Arg_i128;
3179           else if constexpr (is_same_v<_Tp, unsigned __int128>)
3180             return _Arg_u128;
3181 #endif
3183           // N.B. some of these types will never actually be used here,
3184           // because they get normalized to a standard floating-point type.
3185 #if defined __FLT32_DIG__ && ! _GLIBCXX_FLOAT_IS_IEEE_BINARY32
3186           else if constexpr (is_same_v<_Tp, _Float32>)
3187             return _Arg_f32;
3188 #endif
3189 #if defined __FLT64_DIG__ && ! _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
3190           else if constexpr (is_same_v<_Tp, _Float64>)
3191             return _Arg_f64;
3192 #endif
3193 #if _GLIBCXX_FORMAT_F128 == 2
3194           else if constexpr (is_same_v<_Tp, __format::__float128_t>)
3195             return _Arg_f128;
3196 #endif
3197           else if constexpr (is_same_v<_Tp, handle>)
3198             return _Arg_handle;
3199         }
3201       template<typename _Tp>
3202         void
3203         _M_set(_Tp __v) noexcept
3204         {
3205           _M_type = _S_to_enum<_Tp>();
3206           _M_val._M_set(__v);
3207         }
3209       template<typename _Tp>
3210         requires __format::__formattable_with<_Tp, _Context>
3211         explicit
3212         basic_format_arg(_Tp& __v) noexcept
3213         {
3214           using _Td = _Normalize<_Tp>;
3215           if constexpr (is_same_v<_Td, basic_string_view<_CharT>>)
3216             _M_set(_Td{__v.data(), __v.size()});
3217           else
3218             _M_set(static_cast<_Td>(__v));
3219         }
3221       template<typename _Ctx, typename... _Argz>
3222         friend auto
3223         make_format_args(_Argz&&...) noexcept;
3225       template<typename _Visitor, typename _Ctx>
3226         friend decltype(auto)
3227         visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx>);
3229       template<typename _Visitor>
3230         decltype(auto)
3231         _M_visit(_Visitor&& __vis, __format::_Arg_t __type)
3232         {
3233           using namespace __format;
3234           switch (__type)
3235           {
3236             case _Arg_none:
3237               return std::forward<_Visitor>(__vis)(_M_val._M_none);
3238             case _Arg_bool:
3239               return std::forward<_Visitor>(__vis)(_M_val._M_bool);
3240             case _Arg_c:
3241               return std::forward<_Visitor>(__vis)(_M_val._M_c);
3242             case _Arg_i:
3243               return std::forward<_Visitor>(__vis)(_M_val._M_i);
3244             case _Arg_u:
3245               return std::forward<_Visitor>(__vis)(_M_val._M_u);
3246             case _Arg_ll:
3247               return std::forward<_Visitor>(__vis)(_M_val._M_ll);
3248             case _Arg_ull:
3249               return std::forward<_Visitor>(__vis)(_M_val._M_ull);
3250 #if __glibcxx_to_chars // FIXME: need to be able to format these types!
3251             case _Arg_flt:
3252               return std::forward<_Visitor>(__vis)(_M_val._M_flt);
3253             case _Arg_dbl:
3254               return std::forward<_Visitor>(__vis)(_M_val._M_dbl);
3255 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3256             case _Arg_ldbl:
3257               return std::forward<_Visitor>(__vis)(_M_val._M_ldbl);
3258 #else
3259             case _Arg_f128:
3260               return std::forward<_Visitor>(__vis)(_M_val._M_f128);
3261             case _Arg_ibm128:
3262               return std::forward<_Visitor>(__vis)(_M_val._M_ibm128);
3263 #endif
3264 #endif
3265             case _Arg_str:
3266               return std::forward<_Visitor>(__vis)(_M_val._M_str);
3267             case _Arg_sv:
3268               return std::forward<_Visitor>(__vis)(_M_val._M_sv);
3269             case _Arg_ptr:
3270               return std::forward<_Visitor>(__vis)(_M_val._M_ptr);
3271             case _Arg_handle:
3272             {
3273               auto& __h = static_cast<handle&>(_M_val._M_handle);
3274               return std::forward<_Visitor>(__vis)(__h);
3275             }
3276 #ifdef __SIZEOF_INT128__
3277             case _Arg_i128:
3278               return std::forward<_Visitor>(__vis)(_M_val._M_i128);
3279             case _Arg_u128:
3280               return std::forward<_Visitor>(__vis)(_M_val._M_u128);
3281 #endif
3283 #if _GLIBCXX_FORMAT_F128 == 2
3284             case _Arg_f128:
3285               return std::forward<_Visitor>(__vis)(_M_val._M_f128);
3286 #endif
3288             default:
3289               // _Arg_f16 etc.
3290               __builtin_unreachable();
3291           }
3292         }
3293     };
3295   template<typename _Visitor, typename _Context>
3296     inline decltype(auto)
3297     visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
3298     {
3299       return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type);
3300     }
3302 /// @cond undocumented
3303 namespace __format
3305   struct _WidthPrecVisitor
3306   {
3307     template<typename _Tp>
3308       size_t
3309       operator()(_Tp& __arg) const
3310       {
3311         if constexpr (is_same_v<_Tp, monostate>)
3312           __format::__invalid_arg_id_in_format_string();
3313         // _GLIBCXX_RESOLVE_LIB_DEFECTS
3314         // 3720. Restrict the valid types of arg-id for width and precision
3315         // 3721. Allow an arg-id with a value of zero for width
3316         else if constexpr (sizeof(_Tp) <= sizeof(long long))
3317           {
3318             // _GLIBCXX_RESOLVE_LIB_DEFECTS
3319             // 3720. Restrict the valid types of arg-id for width and precision
3320             if constexpr (__is_unsigned_integer<_Tp>::value)
3321               return __arg;
3322             else if constexpr (__is_signed_integer<_Tp>::value)
3323               if (__arg >= 0)
3324                 return __arg;
3325           }
3326         __throw_format_error("format error: argument used for width or "
3327                              "precision must be a non-negative integer");
3328       }
3329   };
3331   template<typename _Context>
3332     inline size_t
3333     __int_from_arg(const basic_format_arg<_Context>& __arg)
3334     { return std::visit_format_arg(_WidthPrecVisitor(), __arg); }
3336   // Pack _Arg_t enum values into a single 60-bit integer.
3337   template<int _Bits, size_t _Nm>
3338     constexpr auto
3339     __pack_arg_types(const array<_Arg_t, _Nm>& __types)
3340     {
3341       __UINT64_TYPE__ __packed_types = 0;
3342       for (auto __i = __types.rbegin(); __i != __types.rend(); ++__i)
3343         __packed_types = (__packed_types << _Bits) | *__i;
3344       return __packed_types;
3345     }
3346 } // namespace __format
3347 /// @endcond
3349   template<typename _Context>
3350     class basic_format_args
3351     {
3352       static constexpr int _S_packed_type_bits = 5; // _Arg_t values [0,20]
3353       static constexpr int _S_packed_type_mask = 0b11111;
3354       static constexpr int _S_max_packed_args = 12;
3356       static_assert( __format::_Arg_max_ <= (1 << _S_packed_type_bits) );
3358       template<typename... _Args>
3359         using _Store = __format::_Arg_store<_Context, _Args...>;
3361       template<typename _Ctx, typename... _Args>
3362         friend class __format::_Arg_store;
3364       using uint64_t = __UINT64_TYPE__;
3365       using _Format_arg = basic_format_arg<_Context>;
3366       using _Format_arg_val = __format::_Arg_value<_Context>;
3368       // If args are packed then the number of args is in _M_packed_size and
3369       // the packed types are in _M_unpacked_size, accessed via _M_type(i).
3370       // If args are not packed then the number of args is in _M_unpacked_size
3371       // and _M_packed_size is zero.
3372       uint64_t _M_packed_size : 4;
3373       uint64_t _M_unpacked_size : 60;
3375       union {
3376         const _Format_arg_val* _M_values; // Active when _M_packed_size != 0
3377         const _Format_arg* _M_args;       // Active when _M_packed_size == 0
3378       };
3380       size_t
3381       _M_size() const noexcept
3382       { return _M_packed_size ? _M_packed_size : _M_unpacked_size; }
3384       typename __format::_Arg_t
3385       _M_type(size_t __i) const noexcept
3386       {
3387         uint64_t __t = _M_unpacked_size >> (__i * _S_packed_type_bits);
3388         return static_cast<__format::_Arg_t>(__t & _S_packed_type_mask);
3389       }
3391       template<typename _Ctx, typename... _Args>
3392         friend auto
3393         make_format_args(_Args&&...) noexcept;
3395       // An array of _Arg_t enums corresponding to _Args...
3396       template<typename... _Args>
3397         static consteval array<__format::_Arg_t, sizeof...(_Args)>
3398         _S_types_to_pack()
3399         { return {_Format_arg::template _S_to_enum<_Args>()...}; }
3401     public:
3402       basic_format_args() noexcept = default;
3404       template<typename... _Args>
3405         basic_format_args(const _Store<_Args...>& __store) noexcept;
3407       [[nodiscard,__gnu__::__always_inline__]]
3408       basic_format_arg<_Context>
3409       get(size_t __i) const noexcept
3410       {
3411         basic_format_arg<_Context> __arg;
3412         if (__i < _M_packed_size)
3413           {
3414             __arg._M_type = _M_type(__i);
3415             __arg._M_val = _M_values[__i];
3416           }
3417         else if (_M_packed_size == 0 && __i < _M_unpacked_size)
3418           __arg = _M_args[__i];
3419         return __arg;
3420       }
3421     };
3423   // _GLIBCXX_RESOLVE_LIB_DEFECTS
3424   // 3810. CTAD for std::basic_format_args
3425   template<typename _Context, typename... _Args>
3426     basic_format_args(__format::_Arg_store<_Context, _Args...>)
3427       -> basic_format_args<_Context>;
3429   template<typename _Context, typename... _Args>
3430     auto
3431     make_format_args(_Args&&... __fmt_args) noexcept;
3433   // An array of type-erased formatting arguments.
3434   template<typename _Context, typename... _Args>
3435     class __format::_Arg_store
3436     {
3437       friend std::basic_format_args<_Context>;
3439       template<typename _Ctx, typename... _Argz>
3440         friend auto
3441 #if _GLIBCXX_INLINE_VERSION
3442         // Needed for PR c++/59526
3443         std::__8::
3444 #else
3445         std::
3446 #endif
3447         make_format_args(_Argz&&...) noexcept;
3449       // For a sufficiently small number of arguments we only store values.
3450       // basic_format_args can get the types from the _Args pack.
3451       static constexpr bool _S_values_only
3452         = sizeof...(_Args) <= basic_format_args<_Context>::_S_max_packed_args;
3454       using _Element_t
3455         = __conditional_t<_S_values_only,
3456                           __format::_Arg_value<_Context>,
3457                           basic_format_arg<_Context>>;
3459       _Element_t _M_args[sizeof...(_Args)];
3461       template<typename _Tp>
3462         static _Element_t
3463         _S_make_elt(_Tp& __v)
3464         {
3465           basic_format_arg<_Context> __arg(__v);
3466           if constexpr (_S_values_only)
3467             return __arg._M_val;
3468           else
3469             return __arg;
3470         }
3472       template<typename... _Tp>
3473         requires (sizeof...(_Tp) == sizeof...(_Args))
3474         [[__gnu__::__always_inline__]]
3475         _Arg_store(_Tp&... __a) noexcept
3476         : _M_args{_S_make_elt(__a)...}
3477         { }
3478     };
3480   template<typename _Context>
3481     class __format::_Arg_store<_Context>
3482     { };
3484   template<typename _Context>
3485     template<typename... _Args>
3486       inline
3487       basic_format_args<_Context>::
3488       basic_format_args(const _Store<_Args...>& __store) noexcept
3489       {
3490         if constexpr (sizeof...(_Args) == 0)
3491           {
3492             _M_packed_size = 0;
3493             _M_unpacked_size = 0;
3494             _M_args = nullptr;
3495           }
3496         else if constexpr (sizeof...(_Args) <= _S_max_packed_args)
3497           {
3498             // The number of packed arguments:
3499             _M_packed_size = sizeof...(_Args);
3500             // The packed type enums:
3501             _M_unpacked_size
3502               = __format::__pack_arg_types<_S_packed_type_bits>(_S_types_to_pack<_Args...>());
3503             // The _Arg_value objects.
3504             _M_values = __store._M_args;
3505           }
3506         else
3507           {
3508             // No packed arguments:
3509             _M_packed_size = 0;
3510             // The number of unpacked arguments:
3511             _M_unpacked_size = sizeof...(_Args);
3512             // The basic_format_arg objects:
3513             _M_args = __store._M_args;
3514           }
3515       }
3517   /// Capture formatting arguments for use by `std::vformat`.
3518   template<typename _Context = format_context, typename... _Args>
3519     [[nodiscard,__gnu__::__always_inline__]]
3520     inline auto
3521     make_format_args(_Args&&... __fmt_args) noexcept
3522     {
3523       using _Fmt_arg = basic_format_arg<_Context>;
3524       using _Store = __format::_Arg_store<_Context, typename _Fmt_arg::template
3525                      _Normalize<remove_reference_t<_Args>>...>;
3526       return _Store(__fmt_args...);
3527     }
3529 #ifdef _GLIBCXX_USE_WCHAR_T
3530   /// Capture formatting arguments for use by `std::vformat` (for wide output).
3531   template<typename... _Args>
3532     [[nodiscard,__gnu__::__always_inline__]]
3533     inline auto
3534     make_wformat_args(_Args&&... __args) noexcept
3535     { return std::make_format_args<wformat_context>(__args...); }
3536 #endif
3538 /// @cond undocumented
3539 namespace __format
3541   template<typename _Out, typename _CharT, typename _Context>
3542     _Out
3543     __do_vformat_to(_Out, basic_string_view<_CharT>,
3544                     const basic_format_args<_Context>&,
3545                     const locale* = nullptr);
3546 } // namespace __format
3547 /// @endcond
3549   /** Context for std::format and similar functions.
3550    *
3551    * A formatting context contains an output iterator and locale to use
3552    * for the formatting operations. Most programs will never need to use
3553    * this class template explicitly. For typical uses of `std::format` the
3554    * library will use the specializations `std::format_context` (for `char`)
3555    * and `std::wformat_context` (for `wchar_t`).
3556    */
3557   template<typename _Out, typename _CharT>
3558     class basic_format_context
3559     {
3560       static_assert( output_iterator<_Out, const _CharT&> );
3562       basic_format_args<basic_format_context> _M_args;
3563       _Out _M_out;
3564       __format::_Optional_locale _M_loc;
3566       basic_format_context(basic_format_args<basic_format_context> __args,
3567                            _Out __out)
3568       : _M_args(__args), _M_out(std::move(__out))
3569       { }
3571       basic_format_context(basic_format_args<basic_format_context> __args,
3572                            _Out __out, const std::locale& __loc)
3573       : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
3574       { }
3576       template<typename _Out2, typename _CharT2, typename _Context2>
3577         friend _Out2
3578         __format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
3579                                   const basic_format_args<_Context2>&,
3580                                   const locale*);
3582     public:
3583       basic_format_context() = default;
3584       ~basic_format_context() = default;
3586       using iterator = _Out;
3587       using char_type = _CharT;
3588       template<typename _Tp>
3589         using formatter_type = formatter<_Tp, _CharT>;
3591       [[nodiscard]]
3592       basic_format_arg<basic_format_context>
3593       arg(size_t __id) const noexcept
3594       { return _M_args.get(__id); }
3596       [[nodiscard]]
3597       std::locale locale() { return _M_loc.value(); }
3599       [[nodiscard]]
3600       iterator out() { return std::move(_M_out); }
3602       void advance_to(iterator __it) { _M_out = std::move(__it); }
3603     };
3606 /// @cond undocumented
3607 namespace __format
3609   // Abstract base class defining an interface for scanning format strings.
3610   // Scan the characters in a format string, dividing it up into strings of
3611   // ordinary characters, escape sequences, and replacement fields.
3612   // Call virtual functions for derived classes to parse format-specifiers
3613   // or write formatted output.
3614   template<typename _CharT>
3615     struct _Scanner
3616     {
3617       using iterator = typename basic_format_parse_context<_CharT>::iterator;
3619       basic_format_parse_context<_CharT> _M_pc;
3621       constexpr explicit
3622       _Scanner(basic_string_view<_CharT> __str, size_t __nargs = -1)
3623       : _M_pc(__str, __nargs)
3624       { }
3626       constexpr iterator begin() const noexcept { return _M_pc.begin(); }
3627       constexpr iterator end() const noexcept { return _M_pc.end(); }
3629       constexpr void
3630       _M_scan()
3631       {
3632         basic_string_view<_CharT> __fmt = _M_fmt_str();
3634         if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
3635           {
3636             _M_pc.advance_to(begin() + 1);
3637             _M_format_arg(_M_pc.next_arg_id());
3638             return;
3639           }
3641         size_t __lbr = __fmt.find('{');
3642         size_t __rbr = __fmt.find('}');
3644         while (__fmt.size())
3645           {
3646             auto __cmp = __lbr <=> __rbr;
3647             if (__cmp == 0)
3648               {
3649                 _M_on_chars(end());
3650                 _M_pc.advance_to(end());
3651                 return;
3652               }
3653             else if (__cmp < 0)
3654               {
3655                 if (__lbr + 1 == __fmt.size()
3656                       || (__rbr == __fmt.npos && __fmt[__lbr + 1] != '{'))
3657                   __format::__unmatched_left_brace_in_format_string();
3658                 const bool __is_escape = __fmt[__lbr + 1] == '{';
3659                 iterator __last = begin() + __lbr + int(__is_escape);
3660                 _M_on_chars(__last);
3661                 _M_pc.advance_to(__last + 1);
3662                 __fmt = _M_fmt_str();
3663                 if (__is_escape)
3664                   {
3665                     if (__rbr != __fmt.npos)
3666                       __rbr -= __lbr + 2;
3667                     __lbr = __fmt.find('{');
3668                   }
3669                 else
3670                   {
3671                     _M_on_replacement_field();
3672                     __fmt = _M_fmt_str();
3673                     __lbr = __fmt.find('{');
3674                     __rbr = __fmt.find('}');
3675                   }
3676               }
3677             else
3678               {
3679                 if (++__rbr == __fmt.size() || __fmt[__rbr] != '}')
3680                   __format::__unmatched_right_brace_in_format_string();
3681                 iterator __last = begin() + __rbr;
3682                 _M_on_chars(__last);
3683                 _M_pc.advance_to(__last + 1);
3684                 __fmt = _M_fmt_str();
3685                 if (__lbr != __fmt.npos)
3686                   __lbr -= __rbr + 1;
3687                 __rbr = __fmt.find('}');
3688               }
3689           }
3690       }
3692       constexpr basic_string_view<_CharT>
3693       _M_fmt_str() const noexcept
3694       { return {begin(), end()}; }
3696       constexpr virtual void _M_on_chars(iterator) { }
3698       constexpr void _M_on_replacement_field()
3699       {
3700         auto __next = begin();
3702         size_t __id;
3703         if (*__next == '}')
3704           __id = _M_pc.next_arg_id();
3705         else if (*__next == ':')
3706           {
3707             __id = _M_pc.next_arg_id();
3708             _M_pc.advance_to(++__next);
3709           }
3710         else
3711           {
3712             auto [__i, __ptr] = __format::__parse_arg_id(begin(), end());
3713             if (!__ptr || !(*__ptr == '}' || *__ptr == ':'))
3714               __format::__invalid_arg_id_in_format_string();
3715             _M_pc.check_arg_id(__id = __i);
3716             if (*__ptr == ':')
3717               {
3718                 _M_pc.advance_to(++__ptr);
3719               }
3720             else
3721               _M_pc.advance_to(__ptr);
3722           }
3723         _M_format_arg(__id);
3724         if (begin() == end() || *begin() != '}')
3725           __format::__unmatched_left_brace_in_format_string();
3726         _M_pc.advance_to(begin() + 1); // Move past '}'
3727       }
3729       constexpr virtual void _M_format_arg(size_t __id) = 0;
3730     };
3732   // Process a format string and format the arguments in the context.
3733   template<typename _Out, typename _CharT>
3734     class _Formatting_scanner : public _Scanner<_CharT>
3735     {
3736     public:
3737       _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
3738                           basic_string_view<_CharT> __str)
3739       : _Scanner<_CharT>(__str), _M_fc(__fc)
3740       { }
3742     private:
3743       basic_format_context<_Out, _CharT>& _M_fc;
3745       using iterator = typename _Scanner<_CharT>::iterator;
3747       constexpr void
3748       _M_on_chars(iterator __last) override
3749       {
3750         basic_string_view<_CharT> __str(this->begin(), __last);
3751         _M_fc.advance_to(__format::__write(_M_fc.out(), __str));
3752       }
3754       constexpr void
3755       _M_format_arg(size_t __id) override
3756       {
3757         using _Context = basic_format_context<_Out, _CharT>;
3758         using handle = typename basic_format_arg<_Context>::handle;
3760         std::visit_format_arg([this](auto& __arg) {
3761           using _Type = remove_reference_t<decltype(__arg)>;
3762           using _Formatter = typename _Context::template formatter_type<_Type>;
3763           if constexpr (is_same_v<_Type, monostate>)
3764             __format::__invalid_arg_id_in_format_string();
3765           else if constexpr (is_same_v<_Type, handle>)
3766             __arg.format(this->_M_pc, this->_M_fc);
3767           else if constexpr (is_default_constructible_v<_Formatter>)
3768             {
3769               _Formatter __f;
3770               this->_M_pc.advance_to(__f.parse(this->_M_pc));
3771               this->_M_fc.advance_to(__f.format(__arg, this->_M_fc));
3772             }
3773           else
3774             static_assert(__format::__formattable_with<_Type, _Context>);
3775         }, _M_fc.arg(__id));
3776       }
3777     };
3779   // Validate a format string for Args.
3780   template<typename _CharT, typename... _Args>
3781     class _Checking_scanner : public _Scanner<_CharT>
3782     {
3783       static_assert(
3784         (is_default_constructible_v<formatter<_Args, _CharT>> && ...),
3785         "std::formatter must be specialized for each type being formatted");
3787     public:
3788       constexpr
3789       _Checking_scanner(basic_string_view<_CharT> __str)
3790       : _Scanner<_CharT>(__str, sizeof...(_Args))
3791       { }
3793     private:
3794       constexpr void
3795       _M_format_arg(size_t __id) override
3796       {
3797         if constexpr (sizeof...(_Args) != 0)
3798           {
3799             if (__id < sizeof...(_Args))
3800               {
3801                 _M_parse_format_spec<_Args...>(__id);
3802                 return;
3803               }
3804           }
3805         __builtin_unreachable();
3806       }
3808       template<typename _Tp, typename... _OtherArgs>
3809         constexpr void
3810         _M_parse_format_spec(size_t __id)
3811         {
3812           if (__id == 0)
3813             {
3814               formatter<_Tp, _CharT> __f;
3815               this->_M_pc.advance_to(__f.parse(this->_M_pc));
3816             }
3817           else if constexpr (sizeof...(_OtherArgs) != 0)
3818             _M_parse_format_spec<_OtherArgs...>(__id - 1);
3819           else
3820             __builtin_unreachable();
3821         }
3822     };
3824   template<typename _Out, typename _CharT, typename _Context>
3825     inline _Out
3826     __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
3827                     const basic_format_args<_Context>& __args,
3828                     const locale* __loc)
3829     {
3830       _Iter_sink<_CharT, _Out> __sink(std::move(__out));
3831       _Sink_iter<_CharT> __sink_out;
3833       if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
3834         __sink_out = __out; // Already a sink iterator, safe to use post-move.
3835       else
3836         __sink_out = __sink.out();
3838       auto __ctx = __loc == nullptr
3839                      ? _Context(__args, __sink_out)
3840                      : _Context(__args, __sink_out, *__loc);
3841       _Formatting_scanner<_Sink_iter<_CharT>, _CharT> __scanner(__ctx, __fmt);
3842       __scanner._M_scan();
3844       if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
3845         return __ctx.out();
3846       else
3847         return std::move(__sink)._M_finish().out;
3848     }
3850 } // namespace __format
3851 /// @endcond
3853   template<typename _CharT, typename... _Args>
3854     template<typename _Tp>
3855       requires convertible_to<const _Tp&, basic_string_view<_CharT>>
3856       consteval
3857       basic_format_string<_CharT, _Args...>::
3858       basic_format_string(const _Tp& __s)
3859       : _M_str(__s)
3860       {
3861         __format::_Checking_scanner<_CharT, remove_cvref_t<_Args>...>
3862           __scanner(_M_str);
3863         __scanner._M_scan();
3864       }
3866   // [format.functions], formatting functions
3868   template<typename _Out> requires output_iterator<_Out, const char&>
3869     [[__gnu__::__always_inline__]]
3870     inline _Out
3871     vformat_to(_Out __out, string_view __fmt, format_args __args)
3872     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
3874 #ifdef _GLIBCXX_USE_WCHAR_T
3875   template<typename _Out> requires output_iterator<_Out, const wchar_t&>
3876     [[__gnu__::__always_inline__]]
3877     inline _Out
3878     vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
3879     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
3880 #endif
3882   template<typename _Out> requires output_iterator<_Out, const char&>
3883     [[__gnu__::__always_inline__]]
3884     inline _Out
3885     vformat_to(_Out __out, const locale& __loc, string_view __fmt,
3886                format_args __args)
3887     {
3888       return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
3889     }
3891 #ifdef _GLIBCXX_USE_WCHAR_T
3892   template<typename _Out> requires output_iterator<_Out, const wchar_t&>
3893     [[__gnu__::__always_inline__]]
3894     inline _Out
3895     vformat_to(_Out __out, const locale& __loc, wstring_view __fmt,
3896                wformat_args __args)
3897     {
3898       return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
3899     }
3900 #endif
3902   [[nodiscard]]
3903   inline string
3904   vformat(string_view __fmt, format_args __args)
3905   {
3906     __format::_Str_sink<char> __buf;
3907     std::vformat_to(__buf.out(), __fmt, __args);
3908     return std::move(__buf).get();
3909   }
3911 #ifdef _GLIBCXX_USE_WCHAR_T
3912   [[nodiscard]]
3913   inline wstring
3914   vformat(wstring_view __fmt, wformat_args __args)
3915   {
3916     __format::_Str_sink<wchar_t> __buf;
3917     std::vformat_to(__buf.out(), __fmt, __args);
3918     return std::move(__buf).get();
3919   }
3920 #endif
3922   [[nodiscard]]
3923   inline string
3924   vformat(const locale& __loc, string_view __fmt, format_args __args)
3925   {
3926     __format::_Str_sink<char> __buf;
3927     std::vformat_to(__buf.out(), __loc, __fmt, __args);
3928     return std::move(__buf).get();
3929   }
3931 #ifdef _GLIBCXX_USE_WCHAR_T
3932   [[nodiscard]]
3933   inline wstring
3934   vformat(const locale& __loc, wstring_view __fmt, wformat_args __args)
3935   {
3936     __format::_Str_sink<wchar_t> __buf;
3937     std::vformat_to(__buf.out(), __loc, __fmt, __args);
3938     return std::move(__buf).get();
3939   }
3940 #endif
3942   template<typename... _Args>
3943     [[nodiscard]]
3944     inline string
3945     format(format_string<_Args...> __fmt, _Args&&... __args)
3946     { return std::vformat(__fmt.get(), std::make_format_args(__args...)); }
3948 #ifdef _GLIBCXX_USE_WCHAR_T
3949   template<typename... _Args>
3950     [[nodiscard]]
3951     inline wstring
3952     format(wformat_string<_Args...> __fmt, _Args&&... __args)
3953     { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); }
3954 #endif
3956   template<typename... _Args>
3957     [[nodiscard]]
3958     inline string
3959     format(const locale& __loc, format_string<_Args...> __fmt,
3960            _Args&&... __args)
3961     {
3962       return std::vformat(__loc, __fmt.get(),
3963                           std::make_format_args(__args...));
3964     }
3966 #ifdef _GLIBCXX_USE_WCHAR_T
3967   template<typename... _Args>
3968     [[nodiscard]]
3969     inline wstring
3970     format(const locale& __loc, wformat_string<_Args...> __fmt,
3971            _Args&&... __args)
3972     {
3973       return std::vformat(__loc, __fmt.get(),
3974                           std::make_wformat_args(__args...));
3975     }
3976 #endif
3978   template<typename _Out, typename... _Args>
3979     requires output_iterator<_Out, const char&>
3980     inline _Out
3981     format_to(_Out __out, format_string<_Args...> __fmt, _Args&&... __args)
3982     {
3983       return std::vformat_to(std::move(__out), __fmt.get(),
3984                              std::make_format_args(std::forward<_Args>(__args)...));
3985     }
3987 #ifdef _GLIBCXX_USE_WCHAR_T
3988   template<typename _Out, typename... _Args>
3989     requires output_iterator<_Out, const wchar_t&>
3990     inline _Out
3991     format_to(_Out __out, wformat_string<_Args...> __fmt, _Args&&... __args)
3992     {
3993       return std::vformat_to(std::move(__out), __fmt.get(),
3994                              std::make_wformat_args(std::forward<_Args>(__args)...));
3995     }
3996 #endif
3998   template<typename _Out, typename... _Args>
3999     requires output_iterator<_Out, const char&>
4000     inline _Out
4001     format_to(_Out __out, const locale& __loc, format_string<_Args...> __fmt,
4002               _Args&&... __args)
4003     {
4004       return std::vformat_to(std::move(__out), __loc, __fmt.get(),
4005                              std::make_format_args(std::forward<_Args>(__args)...));
4006     }
4008 #ifdef _GLIBCXX_USE_WCHAR_T
4009   template<typename _Out, typename... _Args>
4010     requires output_iterator<_Out, const wchar_t&>
4011     inline _Out
4012     format_to(_Out __out, const locale& __loc, wformat_string<_Args...> __fmt,
4013               _Args&&... __args)
4014     {
4015       return std::vformat_to(std::move(__out), __loc, __fmt.get(),
4016                              std::make_wformat_args(std::forward<_Args>(__args)...));
4017     }
4018 #endif
4020   template<typename _Out, typename... _Args>
4021     requires output_iterator<_Out, const char&>
4022     inline format_to_n_result<_Out>
4023     format_to_n(_Out __out, iter_difference_t<_Out> __n,
4024                 format_string<_Args...> __fmt, _Args&&... __args)
4025     {
4026       __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
4027       std::vformat_to(__sink.out(), __fmt.get(),
4028                       std::make_format_args(__args...));
4029       return std::move(__sink)._M_finish();
4030     }
4032 #ifdef _GLIBCXX_USE_WCHAR_T
4033   template<typename _Out, typename... _Args>
4034     requires output_iterator<_Out, const wchar_t&>
4035     inline format_to_n_result<_Out>
4036     format_to_n(_Out __out, iter_difference_t<_Out> __n,
4037                 wformat_string<_Args...> __fmt, _Args&&... __args)
4038     {
4039       __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
4040       std::vformat_to(__sink.out(), __fmt.get(),
4041                       std::make_wformat_args(__args...));
4042       return std::move(__sink)._M_finish();
4043     }
4044 #endif
4046   template<typename _Out, typename... _Args>
4047     requires output_iterator<_Out, const char&>
4048     inline format_to_n_result<_Out>
4049     format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
4050                 format_string<_Args...> __fmt, _Args&&... __args)
4051     {
4052       __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
4053       std::vformat_to(__sink.out(), __loc, __fmt.get(),
4054                       std::make_format_args(__args...));
4055       return std::move(__sink)._M_finish();
4056     }
4058 #ifdef _GLIBCXX_USE_WCHAR_T
4059   template<typename _Out, typename... _Args>
4060     requires output_iterator<_Out, const wchar_t&>
4061     inline format_to_n_result<_Out>
4062     format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
4063                 wformat_string<_Args...> __fmt, _Args&&... __args)
4064     {
4065       __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
4066       std::vformat_to(__sink.out(), __loc, __fmt.get(),
4067                       std::make_wformat_args(__args...));
4068       return std::move(__sink)._M_finish();
4069     }
4070 #endif
4072 /// @cond undocumented
4073 namespace __format
4075 #if 1
4076   template<typename _CharT>
4077     class _Counting_sink final : public _Iter_sink<_CharT, _CharT*>
4078     {
4079     public:
4080       _Counting_sink() : _Iter_sink<_CharT, _CharT*>(nullptr, 0) { }
4082       [[__gnu__::__always_inline__]]
4083       size_t
4084       count() const
4085       { return this->_M_count + this->_M_used().size(); }
4086     };
4087 #else
4088   template<typename _CharT>
4089     class _Counting_sink : public _Buf_sink<_CharT>
4090     {
4091       size_t _M_count = 0;
4093       void
4094       _M_overflow() override
4095       {
4096         if (!std::is_constant_evaluated())
4097           _M_count += this->_M_used().size();
4098         this->_M_rewind();
4099       }
4101     public:
4102       _Counting_sink() = default;
4104       [[__gnu__::__always_inline__]]
4105       size_t
4106       count() noexcept
4107       {
4108         _Counting_sink::_M_overflow();
4109         return _M_count;
4110       }
4111     };
4112 #endif
4113 } // namespace __format
4114 /// @endcond
4116   template<typename... _Args>
4117     [[nodiscard]]
4118     inline size_t
4119     formatted_size(format_string<_Args...> __fmt, _Args&&... __args)
4120     {
4121       __format::_Counting_sink<char> __buf;
4122       std::vformat_to(__buf.out(), __fmt.get(),
4123                       std::make_format_args(std::forward<_Args>(__args)...));
4124       return __buf.count();
4125     }
4127 #ifdef _GLIBCXX_USE_WCHAR_T
4128   template<typename... _Args>
4129     [[nodiscard]]
4130     inline size_t
4131     formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args)
4132     {
4133       __format::_Counting_sink<wchar_t> __buf;
4134       std::vformat_to(__buf.out(), __fmt.get(),
4135                       std::make_wformat_args(std::forward<_Args>(__args)...));
4136       return __buf.count();
4137     }
4138 #endif
4140   template<typename... _Args>
4141     [[nodiscard]]
4142     inline size_t
4143     formatted_size(const locale& __loc, format_string<_Args...> __fmt,
4144                    _Args&&... __args)
4145     {
4146       __format::_Counting_sink<char> __buf;
4147       std::vformat_to(__buf.out(), __loc, __fmt.get(),
4148                       std::make_format_args(std::forward<_Args>(__args)...));
4149       return __buf.count();
4150     }
4152 #ifdef _GLIBCXX_USE_WCHAR_T
4153   template<typename... _Args>
4154     [[nodiscard]]
4155     inline size_t
4156     formatted_size(const locale& __loc, wformat_string<_Args...> __fmt,
4157                    _Args&&... __args)
4158     {
4159       __format::_Counting_sink<wchar_t> __buf;
4160       std::vformat_to(__buf.out(), __loc, __fmt.get(),
4161                       std::make_wformat_args(std::forward<_Args>(__args)...));
4162       return __buf.count();
4163     }
4164 #endif
4166 #if __cpp_lib_format_ranges
4167   // [format.range], formatting of ranges
4168   // [format.range.fmtkind], variable template format_kind
4169   enum class range_format {
4170     disabled,
4171     map,
4172     set,
4173     sequence,
4174     string,
4175     debug_string
4176   };
4178   /// @cond undocumented
4179   template<typename _Rg>
4180     constexpr auto format_kind = not defined(format_kind<_Rg>);
4182   template<typename _Tp>
4183     consteval range_format
4184     __fmt_kind()
4185     {
4186       using _Ref = ranges::range_reference_t<_Tp>;
4187       if constexpr (is_same_v<remove_cvref_t<_Ref>, _Tp>)
4188         return range_format::disabled;
4189       else if constexpr (requires { typename _Tp::key_type; })
4190         {
4191           if constexpr (requires { typename _Tp::mapped_type; })
4192             {
4193               using _Up = remove_cvref_t<_Ref>;
4194               if constexpr (__is_pair<_Up>)
4195                 return range_format::map;
4196               else if constexpr (__is_specialization_of<_Up, tuple>)
4197                 if constexpr (tuple_size_v<_Up> == 2)
4198                   return range_format::map;
4199             }
4200           return range_format::set;
4201         }
4202       else
4203         return range_format::sequence;
4204     }
4205   /// @endcond
4207   /// A constant determining how a range should be formatted.
4208   template<ranges::input_range _Rg> requires same_as<_Rg, remove_cvref_t<_Rg>>
4209     constexpr range_format format_kind<_Rg> = __fmt_kind<_Rg>();
4211   // [format.range.formatter], class template range_formatter
4212   template<typename _Tp, typename _CharT = char>
4213     requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
4214     class range_formatter; // TODO
4216 /// @cond undocumented
4217 namespace __format
4219   // [format.range.fmtdef], class template range-default-formatter
4220   template<range_format _Kind, ranges::input_range _Rg, typename _CharT>
4221     struct __range_default_formatter; // TODO
4222 } // namespace __format
4223 /// @endcond
4225   // [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr],
4226   // specializations for maps, sets, and strings
4227   template<ranges::input_range _Rg, typename _CharT>
4228     requires (format_kind<_Rg> != range_format::disabled)
4229       && formattable<ranges::range_reference_t<_Rg>, _CharT>
4230     struct formatter<_Rg, _CharT>
4231     : __format::__range_default_formatter<format_kind<_Rg>, _Rg, _CharT>
4232     { };
4233 #endif // C++23 formatting ranges
4235 _GLIBCXX_END_NAMESPACE_VERSION
4236 } // namespace std
4237 #endif // __cpp_lib_format
4238 #endif // _GLIBCXX_FORMAT