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