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