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  template<typename _Out>
1188  typename basic_format_context<_Out, _CharT>::iterator
1189  _M_format_character(_CharT __c,
1190  basic_format_context<_Out, _CharT>& __fc) const
1191  {
1192  return __format::__write_padded_as_spec({&__c, 1u}, 1, __fc, _M_spec);
1193  }
1194 
1195  template<typename _Int>
1196  static _CharT
1197  _S_to_character(_Int __i)
1198  {
1199  using _Traits = __gnu_cxx::__int_traits<_CharT>;
1200  if constexpr (is_signed_v<_Int> == is_signed_v<_CharT>)
1201  {
1202  if (_Traits::__min <= __i && __i <= _Traits::__max)
1203  return static_cast<_CharT>(__i);
1204  }
1205  else if constexpr (is_signed_v<_Int>)
1206  {
1207  if (__i >= 0 && make_unsigned_t<_Int>(__i) <= _Traits::__max)
1208  return static_cast<_CharT>(__i);
1209  }
1210  else if (__i <= make_unsigned_t<_CharT>(_Traits::__max))
1211  return static_cast<_CharT>(__i);
1212  __throw_format_error("format error: integer not representable as "
1213  "character");
1214  }
1215 
1216  template<typename _Out>
1217  typename basic_format_context<_Out, _CharT>::iterator
1218  _M_format_int(string_view __narrow_str, size_t __prefix_len,
1219  basic_format_context<_Out, _CharT>& __fc) const
1220  {
1221  size_t __width = _M_spec._M_get_width(__fc);
1222 
1223  basic_string_view<_CharT> __str;
1224  if constexpr (is_same_v<char, _CharT>)
1225  __str = __narrow_str;
1226 #ifdef _GLIBCXX_USE_WCHAR_T
1227  else
1228  {
1229  size_t __n = __narrow_str.size();
1230  auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
1231  std::__to_wstring_numeric(__narrow_str.data(), __n, __p);
1232  __str = {__p, __n};
1233  }
1234 #endif
1235 
1236  if (_M_spec._M_localized)
1237  {
1238  const auto& __l = __fc.locale();
1239  if (__l.name() != "C")
1240  {
1241  auto& __np = use_facet<numpunct<_CharT>>(__l);
1242  string __grp = __np.grouping();
1243  if (!__grp.empty())
1244  {
1245  size_t __n = __str.size() - __prefix_len;
1246  auto __p = (_CharT*)__builtin_alloca(2 * __n
1247  * sizeof(_CharT)
1248  + __prefix_len);
1249  auto __s = __str.data();
1250  char_traits<_CharT>::copy(__p, __s, __prefix_len);
1251  __s += __prefix_len;
1252  auto __end = std::__add_grouping(__p + __prefix_len,
1253  __np.thousands_sep(),
1254  __grp.data(),
1255  __grp.size(),
1256  __s, __s + __n);
1257  __str = {__p, size_t(__end - __p)};
1258  }
1259  }
1260  }
1261 
1262  if (__width <= __str.size())
1263  return __format::__write(__fc.out(), __str);
1264 
1265  char32_t __fill_char = _M_spec._M_fill;
1266  _Align __align = _M_spec._M_align;
1267 
1268  size_t __nfill = __width - __str.size();
1269  auto __out = __fc.out();
1270  if (__align == _Align_default)
1271  {
1272  __align = _Align_right;
1273  if (_M_spec._M_zero_fill)
1274  {
1275  __fill_char = _CharT('0');
1276  // Write sign and base prefix before zero filling.
1277  if (__prefix_len != 0)
1278  {
1279  __out = __format::__write(std::move(__out),
1280  __str.substr(0, __prefix_len));
1281  __str.remove_prefix(__prefix_len);
1282  }
1283  }
1284  else
1285  __fill_char = _CharT(' ');
1286  }
1287  return __format::__write_padded(std::move(__out), __str,
1288  __align, __nfill, __fill_char);
1289  }
1290 
1291 #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
1292  template<typename _Tp>
1293  using make_unsigned_t
1294  = typename __conditional_t<(sizeof(_Tp) <= sizeof(long long)),
1295  std::make_unsigned<_Tp>,
1296  type_identity<unsigned __int128>>::type;
1297 
1298  // std::to_chars is not overloaded for int128 in strict mode.
1299  template<typename _Int>
1300  static to_chars_result
1301  to_chars(char* __first, char* __last, _Int __value, int __base)
1302  { return std::__to_chars_i<_Int>(__first, __last, __value, __base); }
1303 #endif
1304 
1305  _Spec<_CharT> _M_spec{};
1306  };
1307 
1308  // Decide how 128-bit floating-point types should be formatted (or not).
1309  // When supported, the typedef __format::__float128_t is the type that
1310  // format arguments should be converted to for storage in basic_format_arg.
1311  // Define the macro _GLIBCXX_FORMAT_F128 to say they're supported.
1312  // _GLIBCXX_FORMAT_F128=1 means __float128, _Float128 etc. will be formatted
1313  // by converting them to long double (or __ieee128 for powerpc64le).
1314  // _GLIBCXX_FORMAT_F128=2 means basic_format_arg needs to enable explicit
1315  // support for _Float128, rather than formatting it as another type.
1316 #undef _GLIBCXX_FORMAT_F128
1317 
1318 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
1319 
1320  // Format 128-bit floating-point types using __ieee128.
1321  using __float128_t = __ieee128;
1322 # define _GLIBCXX_FORMAT_F128 1
1323 
1324 #ifdef __LONG_DOUBLE_IEEE128__
1325  // These overloads exist in the library, but are not declared.
1326  // Make them available as std::__format::to_chars.
1327  to_chars_result
1328  to_chars(char*, char*, __ibm128) noexcept
1329  __asm("_ZSt8to_charsPcS_e");
1330 
1331  to_chars_result
1332  to_chars(char*, char*, __ibm128, chars_format) noexcept
1333  __asm("_ZSt8to_charsPcS_eSt12chars_format");
1334 
1335  to_chars_result
1336  to_chars(char*, char*, __ibm128, chars_format, int) noexcept
1337  __asm("_ZSt8to_charsPcS_eSt12chars_formati");
1338 #elif __cplusplus == 202002L
1339  to_chars_result
1340  to_chars(char*, char*, __ieee128) noexcept
1341  __asm("_ZSt8to_charsPcS_u9__ieee128");
1342 
1343  to_chars_result
1344  to_chars(char*, char*, __ieee128, chars_format) noexcept
1345  __asm("_ZSt8to_charsPcS_u9__ieee128St12chars_format");
1346 
1347  to_chars_result
1348  to_chars(char*, char*, __ieee128, chars_format, int) noexcept
1349  __asm("_ZSt8to_charsPcS_u9__ieee128St12chars_formati");
1350 #endif
1351 
1352 #elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128
1353 
1354  // Format 128-bit floating-point types using long double.
1355  using __float128_t = long double;
1356 # define _GLIBCXX_FORMAT_F128 1
1357 
1358 #elif __FLT128_DIG__ && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
1359 
1360  // Format 128-bit floating-point types using _Float128.
1361  using __float128_t = _Float128;
1362 # define _GLIBCXX_FORMAT_F128 2
1363 
1364 # if __cplusplus == 202002L
1365  // These overloads exist in the library, but are not declared for C++20.
1366  // Make them available as std::__format::to_chars.
1367  to_chars_result
1368  to_chars(char*, char*, _Float128) noexcept
1369 # if _GLIBCXX_INLINE_VERSION
1370  __asm("_ZNSt3__88to_charsEPcS0_DF128_");
1371 # else
1372  __asm("_ZSt8to_charsPcS_DF128_");
1373 # endif
1374 
1375  to_chars_result
1376  to_chars(char*, char*, _Float128, chars_format) noexcept
1377 # if _GLIBCXX_INLINE_VERSION
1378  __asm("_ZNSt3__88to_charsEPcS0_DF128_NS_12chars_formatE");
1379 # else
1380  __asm("_ZSt8to_charsPcS_DF128_St12chars_format");
1381 # endif
1382 
1383  to_chars_result
1384  to_chars(char*, char*, _Float128, chars_format, int) noexcept
1385 # if _GLIBCXX_INLINE_VERSION
1386  __asm("_ZNSt3__88to_charsEPcS0_DF128_NS_12chars_formatEi");
1387 # else
1388  __asm("_ZSt8to_charsPcS_DF128_St12chars_formati");
1389 # endif
1390 # endif
1391 #endif
1392 
1393  using std::to_chars;
1394 
1395  // We can format a floating-point type iff it is usable with to_chars.
1396  template<typename _Tp>
1397  concept __formattable_float
1398  = is_same_v<remove_cv_t<_Tp>, _Tp> && requires (_Tp __t, char* __p)
1399  { __format::to_chars(__p, __p, __t, chars_format::scientific, 6); };
1400 
1401  template<__char _CharT>
1402  struct __formatter_fp
1403  {
1404  constexpr typename basic_format_parse_context<_CharT>::iterator
1405  parse(basic_format_parse_context<_CharT>& __pc)
1406  {
1407  _Spec<_CharT> __spec{};
1408  const auto __last = __pc.end();
1409  auto __first = __pc.begin();
1410 
1411  auto __finalize = [this, &__spec] {
1412  _M_spec = __spec;
1413  };
1414 
1415  auto __finished = [&] {
1416  if (__first == __last || *__first == '}')
1417  {
1418  __finalize();
1419  return true;
1420  }
1421  return false;
1422  };
1423 
1424  if (__finished())
1425  return __first;
1426 
1427  __first = __spec._M_parse_fill_and_align(__first, __last);
1428  if (__finished())
1429  return __first;
1430 
1431  __first = __spec._M_parse_sign(__first, __last);
1432  if (__finished())
1433  return __first;
1434 
1435  __first = __spec._M_parse_alternate_form(__first, __last);
1436  if (__finished())
1437  return __first;
1438 
1439  __first = __spec._M_parse_zero_fill(__first, __last);
1440  if (__finished())
1441  return __first;
1442 
1443  if (__first[0] != '.')
1444  {
1445  __first = __spec._M_parse_width(__first, __last, __pc);
1446  if (__finished())
1447  return __first;
1448  }
1449 
1450  __first = __spec._M_parse_precision(__first, __last, __pc);
1451  if (__finished())
1452  return __first;
1453 
1454  __first = __spec._M_parse_locale(__first, __last);
1455  if (__finished())
1456  return __first;
1457 
1458  switch (*__first)
1459  {
1460  case 'a':
1461  __spec._M_type = _Pres_a;
1462  ++__first;
1463  break;
1464  case 'A':
1465  __spec._M_type = _Pres_A;
1466  ++__first;
1467  break;
1468  case 'e':
1469  __spec._M_type = _Pres_e;
1470  ++__first;
1471  break;
1472  case 'E':
1473  __spec._M_type = _Pres_E;
1474  ++__first;
1475  break;
1476  case 'f':
1477  __spec._M_type = _Pres_f;
1478  ++__first;
1479  break;
1480  case 'F':
1481  __spec._M_type = _Pres_F;
1482  ++__first;
1483  break;
1484  case 'g':
1485  __spec._M_type = _Pres_g;
1486  ++__first;
1487  break;
1488  case 'G':
1489  __spec._M_type = _Pres_G;
1490  ++__first;
1491  break;
1492  }
1493 
1494  if (__finished())
1495  return __first;
1496 
1497  __format::__failed_to_parse_format_spec();
1498  }
1499 
1500  template<typename _Fp, typename _Out>
1501  typename basic_format_context<_Out, _CharT>::iterator
1502  format(_Fp __v, basic_format_context<_Out, _CharT>& __fc) const
1503  {
1504  std::string __dynbuf;
1505  char __buf[128];
1506  to_chars_result __res{};
1507 
1508  size_t __prec = 6;
1509  bool __use_prec = _M_spec._M_prec_kind != _WP_none;
1510  if (__use_prec)
1511  __prec = _M_spec._M_get_precision(__fc);
1512 
1513  char* __start = __buf + 1; // reserve space for sign
1514  char* __end = __buf + sizeof(__buf);
1515 
1516  chars_format __fmt{};
1517  bool __upper = false;
1518  bool __trailing_zeros = false;
1519  char __expc = 'e';
1520 
1521  switch (_M_spec._M_type)
1522  {
1523  case _Pres_A:
1524  __upper = true;
1525  __expc = 'P';
1526  [[fallthrough]];
1527  case _Pres_a:
1528  if (_M_spec._M_type != _Pres_A)
1529  __expc = 'p';
1530  __fmt = chars_format::hex;
1531  break;
1532  case _Pres_E:
1533  __upper = true;
1534  __expc = 'E';
1535  [[fallthrough]];
1536  case _Pres_e:
1537  __use_prec = true;
1538  __fmt = chars_format::scientific;
1539  break;
1540  case _Pres_F:
1541  __upper = true;
1542  [[fallthrough]];
1543  case _Pres_f:
1544  __use_prec = true;
1545  __fmt = chars_format::fixed;
1546  break;
1547  case _Pres_G:
1548  __upper = true;
1549  __expc = 'E';
1550  [[fallthrough]];
1551  case _Pres_g:
1552  __trailing_zeros = true;
1553  __use_prec = true;
1554  __fmt = chars_format::general;
1555  break;
1556  case _Pres_none:
1557  if (__use_prec)
1558  __fmt = chars_format::general;
1559  break;
1560  default:
1561  __builtin_unreachable();
1562  }
1563 
1564  // Write value into buffer using std::to_chars.
1565  auto __to_chars = [&](char* __b, char* __e) {
1566  if (__use_prec)
1567  return __format::to_chars(__b, __e, __v, __fmt, __prec);
1568  else if (__fmt != chars_format{})
1569  return __format::to_chars(__b, __e, __v, __fmt);
1570  else
1571  return __format::to_chars(__b, __e, __v);
1572  };
1573 
1574  // First try using stack buffer.
1575  __res = __to_chars(__start, __end);
1576 
1577  if (__builtin_expect(__res.ec == errc::value_too_large, 0))
1578  {
1579  // If the buffer is too small it's probably because of a large
1580  // precision, or a very large value in fixed format.
1581  size_t __guess = 8 + __prec;
1582  if (__fmt == chars_format::fixed) // +ddd.prec
1583  {
1584  if constexpr (is_same_v<_Fp, float> || is_same_v<_Fp, double>
1585  || is_same_v<_Fp, long double>)
1586  {
1587  // The number of digits to the left of the decimal point
1588  // is floor(log10(max(abs(__v),1)))+1
1589  int __exp{};
1590  if constexpr (is_same_v<_Fp, float>)
1591  __builtin_frexpf(__v, &__exp);
1592  else if constexpr (is_same_v<_Fp, double>)
1593  __builtin_frexp(__v, &__exp);
1594  else if constexpr (is_same_v<_Fp, long double>)
1595  __builtin_frexpl(__v, &__exp);
1596  if (__exp > 0)
1597  __guess += 1U + __exp * 4004U / 13301U; // log10(2) approx.
1598  }
1599  else
1600  __guess += numeric_limits<_Fp>::max_exponent10;
1601  }
1602  if (__guess <= sizeof(__buf)) [[unlikely]]
1603  __guess = sizeof(__buf) * 2;
1604  __dynbuf.reserve(__guess);
1605 
1606  do
1607  {
1608  auto __overwrite = [&__to_chars, &__res] (char* __p, size_t __n)
1609  {
1610  __res = __to_chars(__p + 1, __p + __n - 1);
1611  return __res.ec == errc{} ? __res.ptr - __p : 0;
1612  };
1613 
1614  __dynbuf.__resize_and_overwrite(__dynbuf.capacity() * 2,
1615  __overwrite);
1616  __start = __dynbuf.data() + 1; // reserve space for sign
1617  __end = __dynbuf.data() + __dynbuf.size();
1618  }
1619  while (__builtin_expect(__res.ec == errc::value_too_large, 0));
1620  }
1621 
1622  // Use uppercase for 'A', 'E', and 'G' formats.
1623  if (__upper)
1624  {
1625  for (char* __p = __start; __p != __res.ptr; ++__p)
1626  *__p = std::toupper(*__p);
1627  }
1628 
1629  bool __have_sign = true;
1630  // Add sign for non-negative values.
1631  if (!__builtin_signbit(__v))
1632  {
1633  if (_M_spec._M_sign == _Sign_plus)
1634  *--__start = '+';
1635  else if (_M_spec._M_sign == _Sign_space)
1636  *--__start = ' ';
1637  else
1638  __have_sign = false;
1639  }
1640 
1641  string_view __narrow_str(__start, __res.ptr - __start);
1642 
1643  // Use alternate form. Ensure decimal point is always present,
1644  // and add trailing zeros (up to precision) for g and G forms.
1645  if (_M_spec._M_alt && __builtin_isfinite(__v))
1646  {
1647  string_view __s = __narrow_str;
1648  size_t __sigfigs; // Number of significant figures.
1649  size_t __z = 0; // Number of trailing zeros to add.
1650  size_t __p; // Position of the exponent character (if any).
1651  size_t __d = __s.find('.'); // Position of decimal point.
1652  if (__d != __s.npos) // Found decimal point.
1653  {
1654  __p = __s.find(__expc, __d + 1);
1655  if (__p == __s.npos)
1656  __p = __s.size();
1657 
1658  // If presentation type is g or G we might need to add zeros.
1659  if (__trailing_zeros)
1660  {
1661  // Find number of digits after first significant figure.
1662  if (__s[__have_sign] != '0')
1663  // A string like "D.D" or "-D.DDD"
1664  __sigfigs = __p - __have_sign - 1;
1665  else
1666  // A string like "0.D" or "-0.0DD".
1667  // Safe to assume there is a non-zero digit, because
1668  // otherwise there would be no decimal point.
1669  __sigfigs = __p - __s.find_first_not_of('0', __d + 1);
1670  }
1671  }
1672  else // No decimal point, we need to insert one.
1673  {
1674  __p = __s.find(__expc); // Find the exponent, if present.
1675  if (__p == __s.npos)
1676  __p = __s.size();
1677  __d = __p; // Position where '.' should be inserted.
1678  __sigfigs = __d - __have_sign;
1679  }
1680 
1681  if (__trailing_zeros && __prec != 0)
1682  {
1683  // For g and G presentation types std::to_chars produces
1684  // no more than prec significant figures. Insert this many
1685  // zeros so the result has exactly prec significant figures.
1686  __z = __prec - __sigfigs;
1687  }
1688 
1689  if (size_t __extras = int(__d == __p) + __z) // How many to add.
1690  {
1691  if (__dynbuf.empty() && __extras <= size_t(__end - __res.ptr))
1692  {
1693  // The stack buffer is large enough for the result.
1694  // Move exponent to make space for extra chars.
1695  __builtin_memmove(__start + __p + __extras,
1696  __start + __p,
1697  __s.size() - __p);
1698  if (__d == __p)
1699  __start[__p++] = '.';
1700  __builtin_memset(__start + __p, '0', __z);
1701  __narrow_str = {__s.data(), __s.size() + __extras};
1702  }
1703  else // Need to switch to the dynamic buffer.
1704  {
1705  __dynbuf.reserve(__s.size() + __extras);
1706  if (__dynbuf.empty())
1707  {
1708  __dynbuf = __s.substr(0, __p);
1709  if (__d == __p)
1710  __dynbuf += '.';
1711  if (__z)
1712  __dynbuf.append(__z, '0');
1713  __dynbuf.append(__s.substr(__p));
1714  }
1715  else
1716  {
1717  __dynbuf.insert(__p, __extras, '0');
1718  if (__d == __p)
1719  __dynbuf[__p] = '.';
1720  }
1721  __narrow_str = __dynbuf;
1722  }
1723  }
1724  }
1725 
1726  basic_string<_CharT> __wstr;
1727  basic_string_view<_CharT> __str;
1728  if constexpr (is_same_v<_CharT, char>)
1729  __str = __narrow_str;
1730 #ifdef _GLIBCXX_USE_WCHAR_T
1731  else
1732  {
1733  __wstr = std::__to_wstring_numeric(__narrow_str);
1734  __str = __wstr;
1735  }
1736 #endif
1737 
1738  if (_M_spec._M_localized && __builtin_isfinite(__v))
1739  {
1740  __wstr = _M_localize(__str, __expc, __fc.locale());
1741  if (!__wstr.empty())
1742  __str = __wstr;
1743  }
1744 
1745  size_t __width = _M_spec._M_get_width(__fc);
1746 
1747  if (__width <= __str.size())
1748  return __format::__write(__fc.out(), __str);
1749 
1750  char32_t __fill_char = _M_spec._M_fill;
1751  _Align __align = _M_spec._M_align;
1752 
1753  size_t __nfill = __width - __str.size();
1754  auto __out = __fc.out();
1755  if (__align == _Align_default)
1756  {
1757  __align = _Align_right;
1758  if (_M_spec._M_zero_fill && __builtin_isfinite(__v))
1759  {
1760  __fill_char = _CharT('0');
1761  // Write sign before zero filling.
1762  if (!__format::__is_xdigit(__narrow_str[0]))
1763  {
1764  *__out++ = __str[0];
1765  __str.remove_prefix(1);
1766  }
1767  }
1768  else
1769  __fill_char = _CharT(' ');
1770  }
1771  return __format::__write_padded(std::move(__out), __str,
1772  __align, __nfill, __fill_char);
1773  }
1774 
1775  // Locale-specific format.
1776  basic_string<_CharT>
1777  _M_localize(basic_string_view<_CharT> __str, char __expc,
1778  const locale& __loc) const
1779  {
1780  basic_string<_CharT> __lstr;
1781 
1782  if (__loc == locale::classic())
1783  return __lstr; // Nothing to do.
1784 
1785  const auto& __np = use_facet<numpunct<_CharT>>(__loc);
1786  const _CharT __point = __np.decimal_point();
1787  const string __grp = __np.grouping();
1788 
1789  _CharT __dot, __exp;
1790  if constexpr (is_same_v<_CharT, char>)
1791  {
1792  __dot = '.';
1793  __exp = __expc;
1794  }
1795  else
1796  {
1797  __dot = L'.';
1798  switch (__expc)
1799  {
1800  case 'e':
1801  __exp = L'e';
1802  break;
1803  case 'E':
1804  __exp = L'E';
1805  break;
1806  case 'p':
1807  __exp = L'p';
1808  break;
1809  case 'P':
1810  __exp = L'P';
1811  break;
1812  default:
1813  __builtin_unreachable();
1814  }
1815  }
1816 
1817  if (__grp.empty() && __point == __dot)
1818  return __lstr; // Locale uses '.' and no grouping.
1819 
1820  size_t __d = __str.find(__dot);
1821  size_t __e = min(__d, __str.find(__exp));
1822  if (__e == __str.npos)
1823  __e = __str.size();
1824  const size_t __r = __str.size() - __e;
1825  auto __overwrite = [&](_CharT* __p, size_t) {
1826  auto __end = std::__add_grouping(__p, __np.thousands_sep(),
1827  __grp.data(), __grp.size(),
1828  __str.data(), __str.data() + __e);
1829  if (__r)
1830  {
1831  if (__d != __str.npos)
1832  {
1833  *__end = __point;
1834  ++__end;
1835  ++__e;
1836  }
1837  if (__r > 1)
1838  __end += __str.copy(__end, __str.npos, __e);
1839  }
1840  return (__end - __p);
1841  };
1842  __lstr.__resize_and_overwrite(__e * 2 + __r, __overwrite);
1843  return __lstr;
1844  }
1845 
1846  _Spec<_CharT> _M_spec{};
1847  };
1848 
1849 } // namespace __format
1850 /// @endcond
1851 
1852  /// Format a character.
1853  template<__format::__char _CharT>
1854  struct formatter<_CharT, _CharT>
1855  {
1856  formatter() = default;
1857 
1858  constexpr typename basic_format_parse_context<_CharT>::iterator
1859  parse(basic_format_parse_context<_CharT>& __pc)
1860  {
1861  return _M_f.template _M_parse<_CharT>(__pc);
1862  }
1863 
1864  template<typename _Out>
1865  typename basic_format_context<_Out, _CharT>::iterator
1866  format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const
1867  {
1868  if (_M_f._M_spec._M_type == __format::_Pres_none
1869  || _M_f._M_spec._M_type == __format::_Pres_c)
1870  return _M_f._M_format_character(__u, __fc);
1871  else if (_M_f._M_spec._M_type == __format::_Pres_esc)
1872  {
1873  // TODO
1874  return __fc.out();
1875  }
1876  else
1877  return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u), __fc);
1878  }
1879 
1880 #if __cpp_lib_format_ranges
1881  constexpr void
1882  set_debug_format() noexcept
1883  { _M_f._M_spec._M_type = __format::_Pres_esc; }
1884 #endif
1885 
1886  private:
1887  __format::__formatter_int<_CharT> _M_f;
1888  };
1889 
1890 #ifdef _GLIBCXX_USE_WCHAR_T
1891  /// Format a char value for wide character output.
1892  template<>
1893  struct formatter<char, wchar_t>
1894  {
1895  formatter() = default;
1896 
1897  constexpr typename basic_format_parse_context<wchar_t>::iterator
1898  parse(basic_format_parse_context<wchar_t>& __pc)
1899  {
1900  return _M_f._M_parse<char>(__pc);
1901  }
1902 
1903  template<typename _Out>
1904  typename basic_format_context<_Out, wchar_t>::iterator
1905  format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
1906  {
1907  if (_M_f._M_spec._M_type == __format::_Pres_none
1908  || _M_f._M_spec._M_type == __format::_Pres_c)
1909  return _M_f._M_format_character(__u, __fc);
1910  else if (_M_f._M_spec._M_type == __format::_Pres_esc)
1911  {
1912  // TODO
1913  return __fc.out();
1914  }
1915  else
1916  return _M_f.format(static_cast<unsigned char>(__u), __fc);
1917  }
1918 
1919 #if __cpp_lib_format_ranges
1920  constexpr void
1921  set_debug_format() noexcept
1922  { _M_f._M_spec._M_type = __format::_Pres_esc; }
1923 #endif
1924 
1925  private:
1926  __format::__formatter_int<wchar_t> _M_f;
1927  };
1928 #endif // USE_WCHAR_T
1929 
1930  /** Format a string.
1931  * @{
1932  */
1933  template<__format::__char _CharT>
1934  struct formatter<_CharT*, _CharT>
1935  {
1936  formatter() = default;
1937 
1938  [[__gnu__::__always_inline__]]
1939  constexpr typename basic_format_parse_context<_CharT>::iterator
1940  parse(basic_format_parse_context<_CharT>& __pc)
1941  { return _M_f.parse(__pc); }
1942 
1943  template<typename _Out>
1944  [[__gnu__::__nonnull__]]
1945  typename basic_format_context<_Out, _CharT>::iterator
1946  format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc) const
1947  { return _M_f.format(__u, __fc); }
1948 
1949 #if __cpp_lib_format_ranges
1950  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
1951 #endif
1952 
1953  private:
1954  __format::__formatter_str<_CharT> _M_f;
1955  };
1956 
1957  template<__format::__char _CharT>
1958  struct formatter<const _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(const _CharT* __u,
1971  basic_format_context<_Out, _CharT>& __fc) const
1972  { return _M_f.format(__u, __fc); }
1973 
1974 #if __cpp_lib_format_ranges
1975  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
1976 #endif
1977 
1978  private:
1979  __format::__formatter_str<_CharT> _M_f;
1980  };
1981 
1982  template<__format::__char _CharT, size_t _Nm>
1983  struct formatter<_CharT[_Nm], _CharT>
1984  {
1985  formatter() = default;
1986 
1987  [[__gnu__::__always_inline__]]
1988  constexpr typename basic_format_parse_context<_CharT>::iterator
1989  parse(basic_format_parse_context<_CharT>& __pc)
1990  { return _M_f.parse(__pc); }
1991 
1992  template<typename _Out>
1993  typename basic_format_context<_Out, _CharT>::iterator
1994  format(const _CharT (&__u)[_Nm],
1995  basic_format_context<_Out, _CharT>& __fc) const
1996  { return _M_f.format({__u, _Nm}, __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<typename _Traits, typename _Alloc>
2007  struct formatter<basic_string<char, _Traits, _Alloc>, char>
2008  {
2009  formatter() = default;
2010 
2011  [[__gnu__::__always_inline__]]
2012  constexpr typename basic_format_parse_context<char>::iterator
2013  parse(basic_format_parse_context<char>& __pc)
2014  { return _M_f.parse(__pc); }
2015 
2016  template<typename _Out>
2017  typename basic_format_context<_Out, char>::iterator
2018  format(const basic_string<char, _Traits, _Alloc>& __u,
2019  basic_format_context<_Out, char>& __fc) const
2020  { return _M_f.format(__u, __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<char> _M_f;
2028  };
2029 
2030 #ifdef _GLIBCXX_USE_WCHAR_T
2031  template<typename _Traits, typename _Alloc>
2032  struct formatter<basic_string<wchar_t, _Traits, _Alloc>, wchar_t>
2033  {
2034  formatter() = default;
2035 
2036  [[__gnu__::__always_inline__]]
2037  constexpr typename basic_format_parse_context<wchar_t>::iterator
2038  parse(basic_format_parse_context<wchar_t>& __pc)
2039  { return _M_f.parse(__pc); }
2040 
2041  template<typename _Out>
2042  typename basic_format_context<_Out, wchar_t>::iterator
2043  format(const basic_string<wchar_t, _Traits, _Alloc>& __u,
2044  basic_format_context<_Out, wchar_t>& __fc) const
2045  { return _M_f.format(__u, __fc); }
2046 
2047 #if __cpp_lib_format_ranges
2048  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2049 #endif
2050 
2051  private:
2052  __format::__formatter_str<wchar_t> _M_f;
2053  };
2054 #endif // USE_WCHAR_T
2055 
2056  template<typename _Traits>
2057  struct formatter<basic_string_view<char, _Traits>, char>
2058  {
2059  formatter() = default;
2060 
2061  [[__gnu__::__always_inline__]]
2062  constexpr typename basic_format_parse_context<char>::iterator
2063  parse(basic_format_parse_context<char>& __pc)
2064  { return _M_f.parse(__pc); }
2065 
2066  template<typename _Out>
2067  typename basic_format_context<_Out, char>::iterator
2068  format(basic_string_view<char, _Traits> __u,
2069  basic_format_context<_Out, char>& __fc) const
2070  { return _M_f.format(__u, __fc); }
2071 
2072 #if __cpp_lib_format_ranges
2073  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2074 #endif
2075 
2076  private:
2077  __format::__formatter_str<char> _M_f;
2078  };
2079 
2080 #ifdef _GLIBCXX_USE_WCHAR_T
2081  template<typename _Traits>
2082  struct formatter<basic_string_view<wchar_t, _Traits>, wchar_t>
2083  {
2084  formatter() = default;
2085 
2086  [[__gnu__::__always_inline__]]
2087  constexpr typename basic_format_parse_context<wchar_t>::iterator
2088  parse(basic_format_parse_context<wchar_t>& __pc)
2089  { return _M_f.parse(__pc); }
2090 
2091  template<typename _Out>
2092  typename basic_format_context<_Out, wchar_t>::iterator
2093  format(basic_string_view<wchar_t, _Traits> __u,
2094  basic_format_context<_Out, wchar_t>& __fc) const
2095  { return _M_f.format(__u, __fc); }
2096 
2097 #if __cpp_lib_format_ranges
2098  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2099 #endif
2100 
2101  private:
2102  __format::__formatter_str<wchar_t> _M_f;
2103  };
2104 #endif // USE_WCHAR_T
2105  /// @}
2106 
2107 /// @cond undocumented
2108 namespace __format
2109 {
2110  // each cv-unqualified arithmetic type ArithmeticT other than
2111  // char, wchar_t, char8_t, char16_t, or char32_t
2112  template<typename _Tp>
2113  constexpr bool __is_formattable_integer = __is_integer<_Tp>::__value;
2114 
2115 #if defined __SIZEOF_INT128__
2116  template<> inline constexpr bool __is_formattable_integer<__int128> = true;
2117  template<> inline constexpr bool __is_formattable_integer<unsigned __int128>
2118  = true;
2119 #endif
2120 
2121  template<> inline constexpr bool __is_formattable_integer<char> = false;
2122  template<> inline constexpr bool __is_formattable_integer<wchar_t> = false;
2123 #ifdef _GLIBCXX_USE_CHAR8_T
2124  template<> inline constexpr bool __is_formattable_integer<char8_t> = false;
2125 #endif
2126  template<> inline constexpr bool __is_formattable_integer<char16_t> = false;
2127  template<> inline constexpr bool __is_formattable_integer<char32_t> = false;
2128 }
2129 /// @endcond
2130 
2131  /// Format an integer.
2132  template<typename _Tp, __format::__char _CharT>
2133  requires __format::__is_formattable_integer<_Tp>
2134  struct formatter<_Tp, _CharT>
2135  {
2136  formatter() = default;
2137 
2138  [[__gnu__::__always_inline__]]
2139  constexpr typename basic_format_parse_context<_CharT>::iterator
2140  parse(basic_format_parse_context<_CharT>& __pc)
2141  {
2142  return _M_f.template _M_parse<_Tp>(__pc);
2143  }
2144 
2145  template<typename _Out>
2146  typename basic_format_context<_Out, _CharT>::iterator
2147  format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
2148  { return _M_f.format(__u, __fc); }
2149 
2150  private:
2151  __format::__formatter_int<_CharT> _M_f;
2152  };
2153 
2154 #if defined __glibcxx_to_chars
2155  /// Format a floating-point value.
2156  template<__format::__formattable_float _Tp, __format::__char _CharT>
2157  struct formatter<_Tp, _CharT>
2158  {
2159  formatter() = default;
2160 
2161  [[__gnu__::__always_inline__]]
2162  constexpr typename basic_format_parse_context<_CharT>::iterator
2163  parse(basic_format_parse_context<_CharT>& __pc)
2164  { return _M_f.parse(__pc); }
2165 
2166  template<typename _Out>
2167  typename basic_format_context<_Out, _CharT>::iterator
2168  format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
2169  { return _M_f.format(__u, __fc); }
2170 
2171  private:
2172  __format::__formatter_fp<_CharT> _M_f;
2173  };
2174 
2175 #if __LDBL_MANT_DIG__ == __DBL_MANT_DIG__
2176  // Reuse __formatter_fp<C>::format<double, Out> for long double.
2177  template<__format::__char _CharT>
2178  struct formatter<long double, _CharT>
2179  {
2180  formatter() = default;
2181 
2182  [[__gnu__::__always_inline__]]
2183  constexpr typename basic_format_parse_context<_CharT>::iterator
2184  parse(basic_format_parse_context<_CharT>& __pc)
2185  { return _M_f.parse(__pc); }
2186 
2187  template<typename _Out>
2188  typename basic_format_context<_Out, _CharT>::iterator
2189  format(long double __u, basic_format_context<_Out, _CharT>& __fc) const
2190  { return _M_f.format((double)__u, __fc); }
2191 
2192  private:
2193  __format::__formatter_fp<_CharT> _M_f;
2194  };
2195 #endif
2196 
2197 #ifdef __STDCPP_FLOAT16_T__
2198  // Reuse __formatter_fp<C>::format<float, Out> for _Float16.
2199  template<__format::__char _CharT>
2200  struct formatter<_Float16, _CharT>
2201  {
2202  formatter() = default;
2203 
2204  [[__gnu__::__always_inline__]]
2205  constexpr typename basic_format_parse_context<_CharT>::iterator
2206  parse(basic_format_parse_context<_CharT>& __pc)
2207  { return _M_f.parse(__pc); }
2208 
2209  template<typename _Out>
2210  typename basic_format_context<_Out, _CharT>::iterator
2211  format(_Float16 __u, basic_format_context<_Out, _CharT>& __fc) const
2212  { return _M_f.format((float)__u, __fc); }
2213 
2214  private:
2215  __format::__formatter_fp<_CharT> _M_f;
2216  };
2217 #endif
2218 
2219 #if defined(__FLT32_DIG__)
2220  // Reuse __formatter_fp<C>::format<float, Out> for _Float32.
2221  template<__format::__char _CharT>
2222  struct formatter<_Float32, _CharT>
2223  {
2224  formatter() = default;
2225 
2226  [[__gnu__::__always_inline__]]
2227  constexpr typename basic_format_parse_context<_CharT>::iterator
2228  parse(basic_format_parse_context<_CharT>& __pc)
2229  { return _M_f.parse(__pc); }
2230 
2231  template<typename _Out>
2232  typename basic_format_context<_Out, _CharT>::iterator
2233  format(_Float32 __u, basic_format_context<_Out, _CharT>& __fc) const
2234  { return _M_f.format((float)__u, __fc); }
2235 
2236  private:
2237  __format::__formatter_fp<_CharT> _M_f;
2238  };
2239 #endif
2240 
2241 #if defined(__FLT64_DIG__)
2242  // Reuse __formatter_fp<C>::format<double, Out> for _Float64.
2243  template<__format::__char _CharT>
2244  struct formatter<_Float64, _CharT>
2245  {
2246  formatter() = default;
2247 
2248  [[__gnu__::__always_inline__]]
2249  constexpr typename basic_format_parse_context<_CharT>::iterator
2250  parse(basic_format_parse_context<_CharT>& __pc)
2251  { return _M_f.parse(__pc); }
2252 
2253  template<typename _Out>
2254  typename basic_format_context<_Out, _CharT>::iterator
2255  format(_Float64 __u, basic_format_context<_Out, _CharT>& __fc) const
2256  { return _M_f.format((double)__u, __fc); }
2257 
2258  private:
2259  __format::__formatter_fp<_CharT> _M_f;
2260  };
2261 #endif
2262 
2263 #if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128 == 1
2264  // Reuse __formatter_fp<C>::format<__float128_t, Out> for _Float128.
2265  template<__format::__char _CharT>
2266  struct formatter<_Float128, _CharT>
2267  {
2268  formatter() = default;
2269 
2270  [[__gnu__::__always_inline__]]
2271  constexpr typename basic_format_parse_context<_CharT>::iterator
2272  parse(basic_format_parse_context<_CharT>& __pc)
2273  { return _M_f.parse(__pc); }
2274 
2275  template<typename _Out>
2276  typename basic_format_context<_Out, _CharT>::iterator
2277  format(_Float128 __u, basic_format_context<_Out, _CharT>& __fc) const
2278  { return _M_f.format((__format::__float128_t)__u, __fc); }
2279 
2280  private:
2281  __format::__formatter_fp<_CharT> _M_f;
2282  };
2283 #endif
2284 
2285 #ifdef __STDCPP_BFLOAT16_T__
2286  // Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t.
2287  template<__format::__char _CharT>
2288  struct formatter<__gnu_cxx::__bfloat16_t, _CharT>
2289  {
2290  formatter() = default;
2291 
2292  [[__gnu__::__always_inline__]]
2293  constexpr typename basic_format_parse_context<_CharT>::iterator
2294  parse(basic_format_parse_context<_CharT>& __pc)
2295  { return _M_f.parse(__pc); }
2296 
2297  template<typename _Out>
2298  typename basic_format_context<_Out, _CharT>::iterator
2299  format(__gnu_cxx::__bfloat16_t __u,
2300  basic_format_context<_Out, _CharT>& __fc) const
2301  { return _M_f.format((float)__u, __fc); }
2302 
2303  private:
2304  __format::__formatter_fp<_CharT> _M_f;
2305  };
2306 #endif
2307 #endif // __cpp_lib_to_chars
2308 
2309  /** Format a pointer.
2310  * @{
2311  */
2312  template<__format::__char _CharT>
2313  struct formatter<const void*, _CharT>
2314  {
2315  formatter() = default;
2316 
2317  constexpr typename basic_format_parse_context<_CharT>::iterator
2318  parse(basic_format_parse_context<_CharT>& __pc)
2319  {
2320  __format::_Spec<_CharT> __spec{};
2321  const auto __last = __pc.end();
2322  auto __first = __pc.begin();
2323 
2324  auto __finalize = [this, &__spec] {
2325  _M_spec = __spec;
2326  };
2327 
2328  auto __finished = [&] {
2329  if (__first == __last || *__first == '}')
2330  {
2331  __finalize();
2332  return true;
2333  }
2334  return false;
2335  };
2336 
2337  if (__finished())
2338  return __first;
2339 
2340  __first = __spec._M_parse_fill_and_align(__first, __last);
2341  if (__finished())
2342  return __first;
2343 
2344 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2345 // P2510R3 Formatting pointers
2346 #if __cplusplus > 202302L || ! defined __STRICT_ANSI__
2347 #define _GLIBCXX_P2518R3 1
2348 #else
2349 #define _GLIBCXX_P2518R3 0
2350 #endif
2351 
2352 #if _GLIBCXX_P2518R3
2353  __first = __spec._M_parse_zero_fill(__first, __last);
2354  if (__finished())
2355  return __first;
2356 #endif
2357 
2358  __first = __spec._M_parse_width(__first, __last, __pc);
2359 
2360  if (__first != __last)
2361  {
2362  if (*__first == 'p')
2363  ++__first;
2364 #if _GLIBCXX_P2518R3
2365  else if (*__first == 'P')
2366  {
2367  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2368  // P2510R3 Formatting pointers
2369  __spec._M_type = __format::_Pres_P;
2370  ++__first;
2371  }
2372 #endif
2373  }
2374 
2375  if (__finished())
2376  return __first;
2377 
2378  __format::__failed_to_parse_format_spec();
2379  }
2380 
2381  template<typename _Out>
2382  typename basic_format_context<_Out, _CharT>::iterator
2383  format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const
2384  {
2385  auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v);
2386  char __buf[2 + sizeof(__v) * 2];
2387  auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf),
2388  __u, 16);
2389  int __n = __ptr - __buf;
2390  __buf[0] = '0';
2391  __buf[1] = 'x';
2392 #if _GLIBCXX_P2518R3
2393  if (_M_spec._M_type == __format::_Pres_P)
2394  {
2395  __buf[1] = 'X';
2396  for (auto __p = __buf + 2; __p != __ptr; ++__p)
2397 #if __has_builtin(__builtin_toupper)
2398  *__p = __builtin_toupper(*__p);
2399 #else
2400  *__p = std::toupper(*__p);
2401 #endif
2402  }
2403 #endif
2404 
2405  basic_string_view<_CharT> __str;
2406  if constexpr (is_same_v<_CharT, char>)
2407  __str = string_view(__buf, __n);
2408 #ifdef _GLIBCXX_USE_WCHAR_T
2409  else
2410  {
2411  auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
2412  std::__to_wstring_numeric(__buf, __n, __p);
2413  __str = wstring_view(__p, __n);
2414  }
2415 #endif
2416 
2417 #if _GLIBCXX_P2518R3
2418  if (_M_spec._M_zero_fill)
2419  {
2420  size_t __width = _M_spec._M_get_width(__fc);
2421  if (__width <= __str.size())
2422  return __format::__write(__fc.out(), __str);
2423 
2424  auto __out = __fc.out();
2425  // Write "0x" or "0X" prefix before zero-filling.
2426  __out = __format::__write(std::move(__out), __str.substr(0, 2));
2427  __str.remove_prefix(2);
2428  size_t __nfill = __width - __n;
2429  return __format::__write_padded(std::move(__out), __str,
2430  __format::_Align_right,
2431  __nfill, _CharT('0'));
2432  }
2433 #endif
2434 
2435  return __format::__write_padded_as_spec(__str, __n, __fc, _M_spec,
2436  __format::_Align_right);
2437  }
2438 
2439  private:
2440  __format::_Spec<_CharT> _M_spec{};
2441  };
2442 
2443  template<__format::__char _CharT>
2444  struct formatter<void*, _CharT>
2445  {
2446  formatter() = default;
2447 
2448  [[__gnu__::__always_inline__]]
2449  constexpr typename basic_format_parse_context<_CharT>::iterator
2450  parse(basic_format_parse_context<_CharT>& __pc)
2451  { return _M_f.parse(__pc); }
2452 
2453  template<typename _Out>
2454  typename basic_format_context<_Out, _CharT>::iterator
2455  format(void* __v, basic_format_context<_Out, _CharT>& __fc) const
2456  { return _M_f.format(__v, __fc); }
2457 
2458  private:
2459  formatter<const void*, _CharT> _M_f;
2460  };
2461 
2462  template<__format::__char _CharT>
2463  struct formatter<nullptr_t, _CharT>
2464  {
2465  formatter() = default;
2466 
2467  [[__gnu__::__always_inline__]]
2468  constexpr typename basic_format_parse_context<_CharT>::iterator
2469  parse(basic_format_parse_context<_CharT>& __pc)
2470  { return _M_f.parse(__pc); }
2471 
2472  template<typename _Out>
2473  typename basic_format_context<_Out, _CharT>::iterator
2474  format(nullptr_t, basic_format_context<_Out, _CharT>& __fc) const
2475  { return _M_f.format(nullptr, __fc); }
2476 
2477  private:
2478  formatter<const void*, _CharT> _M_f;
2479  };
2480  /// @}
2481 
2482 #if defined _GLIBCXX_USE_WCHAR_T && __cpp_lib_format_ranges
2483  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2484  // 3944. Formatters converting sequences of char to sequences of wchar_t
2485 
2486  namespace __format { struct __disabled; }
2487 
2488  // std::formatter<__disabled, C> uses the primary template, which is disabled.
2489  template<>
2490  struct formatter<char*, wchar_t>
2491  : private formatter<__format::__disabled, wchar_t> { };
2492  template<>
2493  struct formatter<const char*, wchar_t>
2494  : private formatter<__format::__disabled, wchar_t> { };
2495  template<size_t _Nm>
2496  struct formatter<char[_Nm], wchar_t>
2497  : private formatter<__format::__disabled, wchar_t> { };
2498  template<class _Traits, class _Allocator>
2499  struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t>
2500  : private formatter<__format::__disabled, wchar_t> { };
2501  template<class _Traits>
2502  struct formatter<basic_string_view<char, _Traits>, wchar_t>
2503  : private formatter<__format::__disabled, wchar_t> { };
2504 #endif
2505 
2506 /// @cond undocumented
2507 namespace __format
2508 {
2509  template<typename _Tp, typename _Context,
2510  typename _Formatter
2511  = typename _Context::template formatter_type<remove_const_t<_Tp>>,
2512  typename _ParseContext
2513  = basic_format_parse_context<typename _Context::char_type>>
2514  concept __parsable_with
2515  = semiregular<_Formatter>
2516  && requires (_Formatter __f, _ParseContext __pc)
2517  {
2518  { __f.parse(__pc) } -> same_as<typename _ParseContext::iterator>;
2519  };
2520 
2521  template<typename _Tp, typename _Context,
2522  typename _Formatter
2523  = typename _Context::template formatter_type<remove_const_t<_Tp>>,
2524  typename _ParseContext
2525  = basic_format_parse_context<typename _Context::char_type>>
2526  concept __formattable_with
2527  = semiregular<_Formatter>
2528  && requires (const _Formatter __cf, _Tp&& __t, _Context __fc)
2529  {
2530  { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>;
2531  };
2532 
2533  // An unspecified output iterator type used in the `formattable` concept.
2534  template<typename _CharT>
2535  using _Iter_for = back_insert_iterator<basic_string<_CharT>>;
2536 
2537  template<typename _Tp, typename _CharT,
2538  typename _Context = basic_format_context<_Iter_for<_CharT>, _CharT>>
2539  concept __formattable_impl
2540  = __parsable_with<_Tp, _Context> && __formattable_with<_Tp, _Context>;
2541 
2542 } // namespace __format
2543 /// @endcond
2544 
2545 // Concept std::formattable was introduced by P2286R8 "Formatting Ranges",
2546 // but we can't guard it with __cpp_lib_format_ranges until we define that!
2547 #if __cplusplus > 202002L
2548  // [format.formattable], concept formattable
2549  template<typename _Tp, typename _CharT>
2550  concept formattable
2551  = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>;
2552 #endif
2553 
2554 #if __cpp_lib_format_ranges
2555  /// @cond undocumented
2556 namespace __format
2557 {
2558  template<typename _Rg, typename _CharT>
2559  concept __const_formattable_range
2560  = ranges::input_range<const _Rg>
2561  && formattable<ranges::range_reference_t<const _Rg>, _CharT>;
2562 
2563  template<typename _Rg, typename _CharT>
2564  using __maybe_const_range
2565  = conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>;
2566 } // namespace __format
2567  /// @endcond
2568 #endif // format_ranges
2569 
2570  /// An iterator after the last character written, and the number of
2571  /// characters that would have been written.
2572  template<typename _Out>
2573  struct format_to_n_result
2574  {
2575  _Out out;
2576  iter_difference_t<_Out> size;
2577  };
2578 
2579 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
2580 template<typename, typename> class vector;
2581 _GLIBCXX_END_NAMESPACE_CONTAINER
2582 
2583 /// @cond undocumented
2584 namespace __format
2585 {
2586  template<typename _CharT>
2587  class _Sink_iter
2588  {
2589  _Sink<_CharT>* _M_sink = nullptr;
2590 
2591  public:
2592  using iterator_category = output_iterator_tag;
2593  using value_type = void;
2594  using difference_type = ptrdiff_t;
2595  using pointer = void;
2596  using reference = void;
2597 
2598  _Sink_iter() = default;
2599  _Sink_iter(const _Sink_iter&) = default;
2600  _Sink_iter& operator=(const _Sink_iter&) = default;
2601 
2602  [[__gnu__::__always_inline__]]
2603  explicit constexpr
2604  _Sink_iter(_Sink<_CharT>& __sink) : _M_sink(std::addressof(__sink)) { }
2605 
2606  [[__gnu__::__always_inline__]]
2607  constexpr _Sink_iter&
2608  operator=(_CharT __c)
2609  {
2610  _M_sink->_M_write(__c);
2611  return *this;
2612  }
2613 
2614  [[__gnu__::__always_inline__]]
2615  constexpr _Sink_iter&
2616  operator=(basic_string_view<_CharT> __s)
2617  {
2618  _M_sink->_M_write(__s);
2619  return *this;
2620  }
2621 
2622  [[__gnu__::__always_inline__]]
2623  constexpr _Sink_iter&
2624  operator*() { return *this; }
2625 
2626  [[__gnu__::__always_inline__]]
2627  constexpr _Sink_iter&
2628  operator++() { return *this; }
2629 
2630  [[__gnu__::__always_inline__]]
2631  constexpr _Sink_iter
2632  operator++(int) { return *this; }
2633 
2634  auto
2635  _M_reserve(size_t __n) const
2636  { return _M_sink->_M_reserve(__n); }
2637  };
2638 
2639  // Abstract base class for type-erased character sinks.
2640  // All formatting and output is done via this type's iterator,
2641  // to reduce the number of different template instantiations.
2642  template<typename _CharT>
2643  class _Sink
2644  {
2645  friend class _Sink_iter<_CharT>;
2646 
2647  span<_CharT> _M_span;
2648  typename span<_CharT>::iterator _M_next;
2649 
2650  // Called when the span is full, to make more space available.
2651  // Precondition: _M_next != _M_span.begin()
2652  // Postcondition: _M_next != _M_span.end()
2653  // TODO: remove the precondition? could make overflow handle it.
2654  virtual void _M_overflow() = 0;
2655 
2656  protected:
2657  // Precondition: __span.size() != 0
2658  [[__gnu__::__always_inline__]]
2659  explicit constexpr
2660  _Sink(span<_CharT> __span) noexcept
2661  : _M_span(__span), _M_next(__span.begin())
2662  { }
2663 
2664  // The portion of the span that has been written to.
2665  [[__gnu__::__always_inline__]]
2666  span<_CharT>
2667  _M_used() const noexcept
2668  { return _M_span.first(_M_next - _M_span.begin()); }
2669 
2670  // The portion of the span that has not been written to.
2671  [[__gnu__::__always_inline__]]
2672  constexpr span<_CharT>
2673  _M_unused() const noexcept
2674  { return _M_span.subspan(_M_next - _M_span.begin()); }
2675 
2676  // Use the start of the span as the next write position.
2677  [[__gnu__::__always_inline__]]
2678  constexpr void
2679  _M_rewind() noexcept
2680  { _M_next = _M_span.begin(); }
2681 
2682  // Replace the current output range.
2683  void
2684  _M_reset(span<_CharT> __s, size_t __pos = 0) noexcept
2685  {
2686  _M_span = __s;
2687  _M_next = __s.begin() + __pos;
2688  }
2689 
2690  // Called by the iterator for *it++ = c
2691  constexpr void
2692  _M_write(_CharT __c)
2693  {
2694  *_M_next++ = __c;
2695  if (_M_next - _M_span.begin() == std::ssize(_M_span)) [[unlikely]]
2696  _M_overflow();
2697  }
2698 
2699  constexpr void
2700  _M_write(basic_string_view<_CharT> __s)
2701  {
2702  span __to = _M_unused();
2703  while (__to.size() <= __s.size())
2704  {
2705  __s.copy(__to.data(), __to.size());
2706  _M_next += __to.size();
2707  __s.remove_prefix(__to.size());
2708  _M_overflow();
2709  __to = _M_unused();
2710  }
2711  if (__s.size())
2712  {
2713  __s.copy(__to.data(), __s.size());
2714  _M_next += __s.size();
2715  }
2716  }
2717 
2718  // A successful _Reservation can be used to directly write
2719  // up to N characters to the sink to avoid unwanted buffering.
2720  struct _Reservation
2721  {
2722  // True if the reservation was successful, false otherwise.
2723  explicit operator bool() const noexcept { return _M_sink; }
2724  // A pointer to write directly to the sink.
2725  _CharT* get() const noexcept { return _M_sink->_M_next.operator->(); }
2726  // Add n to the _M_next iterator for the sink.
2727  void _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
2728  _Sink* _M_sink;
2729  };
2730 
2731  // Attempt to reserve space to write n characters to the sink.
2732  // If anything is written to the reservation then there must be a call
2733  // to _M_bump(N2) before any call to another member function of *this,
2734  // where N2 is the number of characters written.
2735  virtual _Reservation
2736  _M_reserve(size_t __n)
2737  {
2738  if (__n <= _M_unused().size())
2739  return { this };
2740 
2741  if (__n <= _M_span.size()) // Cannot meet the request.
2742  {
2743  _M_overflow(); // Make more space available.
2744  if (__n <= _M_unused().size())
2745  return { this };
2746  }
2747  return { nullptr };
2748  }
2749 
2750  // Update the next output position after writing directly to the sink.
2751  // pre: no calls to _M_write or _M_overflow since _M_reserve.
2752  virtual void
2753  _M_bump(size_t __n)
2754  { _M_next += __n; }
2755 
2756  public:
2757  _Sink(const _Sink&) = delete;
2758  _Sink& operator=(const _Sink&) = delete;
2759 
2760  [[__gnu__::__always_inline__]]
2761  constexpr _Sink_iter<_CharT>
2762  out() noexcept
2763  { return _Sink_iter<_CharT>(*this); }
2764  };
2765 
2766  // A sink with an internal buffer. This is used to implement concrete sinks.
2767  template<typename _CharT>
2768  class _Buf_sink : public _Sink<_CharT>
2769  {
2770  protected:
2771  _CharT _M_buf[32 * sizeof(void*) / sizeof(_CharT)];
2772 
2773  [[__gnu__::__always_inline__]]
2774  constexpr
2775  _Buf_sink() noexcept
2776  : _Sink<_CharT>(_M_buf)
2777  { }
2778  };
2779 
2780  using _GLIBCXX_STD_C::vector;
2781 
2782  // A sink that fills a sequence (e.g. std::string, std::vector, std::deque).
2783  // Writes to a buffer then appends that to the sequence when it fills up.
2784  template<typename _Seq>
2785  class _Seq_sink final : public _Buf_sink<typename _Seq::value_type>
2786  {
2787  using _CharT = typename _Seq::value_type;
2788 
2789  _Seq _M_seq;
2790 
2791  // Transfer buffer contents to the sequence, so buffer can be refilled.
2792  void
2793  _M_overflow() override
2794  {
2795  auto __s = this->_M_used();
2796  if (__s.empty()) [[unlikely]]
2797  return; // Nothing in the buffer to transfer to _M_seq.
2798 
2799  // If _M_reserve was called then _M_bump must have been called too.
2800  _GLIBCXX_DEBUG_ASSERT(__s.data() != _M_seq.data());
2801 
2802  if constexpr (__is_specialization_of<_Seq, basic_string>)
2803  _M_seq.append(__s.data(), __s.size());
2804  else
2805  _M_seq.insert(_M_seq.end(), __s.begin(), __s.end());
2806 
2807  // Make the whole of _M_buf available for the next write:
2808  this->_M_rewind();
2809  }
2810 
2811  typename _Sink<_CharT>::_Reservation
2812  _M_reserve(size_t __n) override
2813  {
2814  // We might already have n characters available in this->_M_unused(),
2815  // but the whole point of this function is to be an optimization for
2816  // the std::format("{}", x) case. We want to avoid writing to _M_buf
2817  // and then copying that into a basic_string if possible, so this
2818  // function prefers to create space directly in _M_seq rather than
2819  // using _M_buf.
2820 
2821  if constexpr (__is_specialization_of<_Seq, basic_string>
2822  || __is_specialization_of<_Seq, vector>)
2823  {
2824  // Flush the buffer to _M_seq first (should not be needed).
2825  if (this->_M_used().size()) [[unlikely]]
2826  _Seq_sink::_M_overflow();
2827 
2828  // Expand _M_seq to make __n new characters available:
2829  const auto __sz = _M_seq.size();
2830  if constexpr (is_same_v<string, _Seq> || is_same_v<wstring, _Seq>)
2831  _M_seq.__resize_and_overwrite(__sz + __n,
2832  [](auto, auto __n2) {
2833  return __n2;
2834  });
2835  else
2836  _M_seq.resize(__sz + __n);
2837 
2838  // Set _M_used() to be a span over the original part of _M_seq
2839  // and _M_unused() to be the extra capacity we just created:
2840  this->_M_reset(_M_seq, __sz);
2841  return { this };
2842  }
2843  else // Try to use the base class' buffer.
2844  return _Sink<_CharT>::_M_reserve(__n);
2845  }
2846 
2847  void
2848  _M_bump(size_t __n) override
2849  {
2850  if constexpr (__is_specialization_of<_Seq, basic_string>
2851  || __is_specialization_of<_Seq, vector>)
2852  {
2853  auto __s = this->_M_used();
2854  _GLIBCXX_DEBUG_ASSERT(__s.data() == _M_seq.data());
2855  // Truncate the sequence to the part that was actually written to:
2856  _M_seq.resize(__s.size() + __n);
2857  // Switch back to using buffer:
2858  this->_M_reset(this->_M_buf);
2859  }
2860  }
2861 
2862  public:
2863  // TODO: for SSO string, use SSO buffer as initial span, then switch
2864  // to _M_buf if it overflows? Or even do that for all unused capacity?
2865 
2866  [[__gnu__::__always_inline__]]
2867  _Seq_sink() noexcept(is_nothrow_default_constructible_v<_Seq>)
2868  { }
2869 
2870  _Seq_sink(_Seq&& __s) noexcept(is_nothrow_move_constructible_v<_Seq>)
2871  : _M_seq(std::move(__s))
2872  { }
2873 
2874  using _Sink<_CharT>::out;
2875 
2876  _Seq
2877  get() &&
2878  {
2879  if (this->_M_used().size() != 0)
2880  _Seq_sink::_M_overflow();
2881  return std::move(_M_seq);
2882  }
2883 
2884  // A writable span that views everything written to the sink.
2885  // Will be either a view over _M_seq or the used part of _M_buf.
2886  span<_CharT>
2887  view()
2888  {
2889  auto __s = this->_M_used();
2890  if (_M_seq.size())
2891  {
2892  if (__s.size() != 0)
2893  _Seq_sink::_M_overflow();
2894  return _M_seq;
2895  }
2896  return __s;
2897  }
2898  };
2899 
2900  template<typename _CharT, typename _Alloc = allocator<_CharT>>
2901  using _Str_sink
2902  = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>;
2903 
2904  // template<typename _CharT, typename _Alloc = allocator<_CharT>>
2905  // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>;
2906 
2907  // A sink that writes to an output iterator.
2908  // Writes to a fixed-size buffer and then flushes to the output iterator
2909  // when the buffer fills up.
2910  template<typename _CharT, typename _OutIter>
2911  class _Iter_sink : public _Buf_sink<_CharT>
2912  {
2913  _OutIter _M_out;
2914  iter_difference_t<_OutIter> _M_max;
2915 
2916  protected:
2917  size_t _M_count = 0;
2918 
2919  void
2920  _M_overflow() override
2921  {
2922  auto __s = this->_M_used();
2923  if (_M_max < 0) // No maximum.
2924  _M_out = ranges::copy(__s, std::move(_M_out)).out;
2925  else if (_M_count < static_cast<size_t>(_M_max))
2926  {
2927  auto __max = _M_max - _M_count;
2928  span<_CharT> __first;
2929  if (__max < __s.size())
2930  __first = __s.first(static_cast<size_t>(__max));
2931  else
2932  __first = __s;
2933  _M_out = ranges::copy(__first, std::move(_M_out)).out;
2934  }
2935  this->_M_rewind();
2936  _M_count += __s.size();
2937  }
2938 
2939  public:
2940  [[__gnu__::__always_inline__]]
2941  explicit
2942  _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __max = -1)
2943  : _M_out(std::move(__out)), _M_max(__max)
2944  { }
2945 
2946  using _Sink<_CharT>::out;
2947 
2948  format_to_n_result<_OutIter>
2949  _M_finish() &&
2950  {
2951  if (this->_M_used().size() != 0)
2952  _Iter_sink::_M_overflow();
2953  iter_difference_t<_OutIter> __count(_M_count);
2954  return { std::move(_M_out), __count };
2955  }
2956  };
2957 
2958  // Partial specialization for contiguous iterators.
2959  // No buffer is used, characters are written straight to the iterator.
2960  // We do not know the size of the output range, so the span size just grows
2961  // as needed. The end of the span might be an invalid pointer outside the
2962  // valid range, but we never actually call _M_span.end(). This class does
2963  // not introduce any invalid pointer arithmetic or overflows that would not
2964  // have happened anyway.
2965  template<typename _CharT, contiguous_iterator _OutIter>
2966  requires same_as<iter_value_t<_OutIter>, _CharT>
2967  class _Iter_sink<_CharT, _OutIter> : public _Sink<_CharT>
2968  {
2969  _OutIter _M_first;
2970  iter_difference_t<_OutIter> _M_max = -1;
2971  protected:
2972  size_t _M_count = 0;
2973  private:
2974  _CharT _M_buf[64]; // Write here after outputting _M_max characters.
2975 
2976  protected:
2977  void
2978  _M_overflow() override
2979  {
2980  if (this->_M_unused().size() != 0)
2981  return; // No need to switch to internal buffer yet.
2982 
2983  auto __s = this->_M_used();
2984 
2985  if (_M_max >= 0)
2986  {
2987  _M_count += __s.size();
2988  // Span was already sized for the maximum character count,
2989  // if it overflows then any further output must go to the
2990  // internal buffer, to be discarded.
2991  this->_M_reset(this->_M_buf);
2992  }
2993  else
2994  {
2995  // No maximum character count. Just extend the span to allow
2996  // writing more characters to it.
2997  this->_M_reset({__s.data(), __s.size() + 1024}, __s.size());
2998  }
2999  }
3000 
3001  typename _Sink<_CharT>::_Reservation
3002  _M_reserve(size_t __n) final
3003  {
3004  auto __avail = this->_M_unused();
3005  if (__n > __avail.size())
3006  {
3007  if (_M_max >= 0)
3008  return {}; // cannot grow
3009 
3010  auto __s = this->_M_used();
3011  this->_M_reset({__s.data(), __s.size() + __n}, __s.size());
3012  }
3013  return { this };
3014  }
3015 
3016  private:
3017  static span<_CharT>
3018  _S_make_span(_CharT* __ptr, iter_difference_t<_OutIter> __n,
3019  span<_CharT> __buf) noexcept
3020  {
3021  if (__n == 0)
3022  return __buf; // Only write to the internal buffer.
3023 
3024  if (__n > 0)
3025  {
3026  if constexpr (!is_integral_v<iter_difference_t<_OutIter>>
3027  || sizeof(__n) > sizeof(size_t))
3028  {
3029  // __int128 or __detail::__max_diff_type
3030  auto __m = iter_difference_t<_OutIter>((size_t)-1);
3031  if (__n > __m)
3032  __n = __m;
3033  }
3034  return {__ptr, (size_t)__n};
3035  }
3036 
3037 #if __has_builtin(__builtin_dynamic_object_size)
3038  if (size_t __bytes = __builtin_dynamic_object_size(__ptr, 2))
3039  return {__ptr, __bytes / sizeof(_CharT)};
3040 #endif
3041  // Avoid forming a pointer to a different memory page.
3042  const auto __off = reinterpret_cast<__UINTPTR_TYPE__>(__ptr) % 1024;
3043  __n = (1024 - __off) / sizeof(_CharT);
3044  if (__n > 0) [[likely]]
3045  return {__ptr, static_cast<size_t>(__n)};
3046  else // Misaligned/packed buffer of wchar_t?
3047  return {__ptr, 1};
3048  }
3049 
3050  public:
3051  explicit
3052  _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __n = -1) noexcept
3053  : _Sink<_CharT>(_S_make_span(std::to_address(__out), __n, _M_buf)),
3054  _M_first(__out), _M_max(__n)
3055  { }
3056 
3057  format_to_n_result<_OutIter>
3058  _M_finish() &&
3059  {
3060  auto __s = this->_M_used();
3061  if (__s.data() == _M_buf)
3062  {
3063  // Switched to internal buffer, so must have written _M_max.
3064  iter_difference_t<_OutIter> __count(_M_count + __s.size());
3065  return { _M_first + _M_max, __count };
3066  }
3067  else // Not using internal buffer yet
3068  {
3069  iter_difference_t<_OutIter> __count(__s.size());
3070  return { _M_first + __count, __count };
3071  }
3072  }
3073  };
3074 
3075  enum _Arg_t : unsigned char {
3076  _Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull,
3077  _Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr, _Arg_handle,
3078  _Arg_i128, _Arg_u128,
3079  _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, // These are unused.
3080 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3081  _Arg_next_value_,
3082  _Arg_f128 = _Arg_ldbl,
3083  _Arg_ibm128 = _Arg_next_value_,
3084 #else
3085  _Arg_f128,
3086 #endif
3087  _Arg_max_
3088  };
3089 
3090  template<typename _Context>
3091  struct _Arg_value
3092  {
3093  using _CharT = typename _Context::char_type;
3094 
3095  struct _HandleBase
3096  {
3097  const void* _M_ptr;
3098  void (*_M_func)();
3099  };
3100 
3101  union
3102  {
3103  monostate _M_none;
3104  bool _M_bool;
3105  _CharT _M_c;
3106  int _M_i;
3107  unsigned _M_u;
3108  long long _M_ll;
3109  unsigned long long _M_ull;
3110  float _M_flt;
3111  double _M_dbl;
3112 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // No long double if it's ambiguous.
3113  long double _M_ldbl;
3114 #endif
3115  const _CharT* _M_str;
3116  basic_string_view<_CharT> _M_sv;
3117  const void* _M_ptr;
3118  _HandleBase _M_handle;
3119 #ifdef __SIZEOF_INT128__
3120  __int128 _M_i128;
3121  unsigned __int128 _M_u128;
3122 #endif
3123 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3124  __ieee128 _M_f128;
3125  __ibm128 _M_ibm128;
3126 #elif _GLIBCXX_FORMAT_F128 == 2
3127  __float128_t _M_f128;
3128 #endif
3129  };
3130 
3131  [[__gnu__::__always_inline__]]
3132  _Arg_value() : _M_none() { }
3133 
3134 #if 0
3135  template<typename _Tp>
3136  _Arg_value(in_place_type_t<_Tp>, _Tp __val)
3137  { _S_get<_Tp>() = __val; }
3138 #endif
3139 
3140  template<typename _Tp, typename _Self>
3141  [[__gnu__::__always_inline__]]
3142  static auto&
3143  _S_get(_Self& __u) noexcept
3144  {
3145  if constexpr (is_same_v<_Tp, bool>)
3146  return __u._M_bool;
3147  else if constexpr (is_same_v<_Tp, _CharT>)
3148  return __u._M_c;
3149  else if constexpr (is_same_v<_Tp, int>)
3150  return __u._M_i;
3151  else if constexpr (is_same_v<_Tp, unsigned>)
3152  return __u._M_u;
3153  else if constexpr (is_same_v<_Tp, long long>)
3154  return __u._M_ll;
3155  else if constexpr (is_same_v<_Tp, unsigned long long>)
3156  return __u._M_ull;
3157  else if constexpr (is_same_v<_Tp, float>)
3158  return __u._M_flt;
3159  else if constexpr (is_same_v<_Tp, double>)
3160  return __u._M_dbl;
3161 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3162  else if constexpr (is_same_v<_Tp, long double>)
3163  return __u._M_ldbl;
3164 #else
3165  else if constexpr (is_same_v<_Tp, __ieee128>)
3166  return __u._M_f128;
3167  else if constexpr (is_same_v<_Tp, __ibm128>)
3168  return __u._M_ibm128;
3169 #endif
3170  else if constexpr (is_same_v<_Tp, const _CharT*>)
3171  return __u._M_str;
3172  else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
3173  return __u._M_sv;
3174  else if constexpr (is_same_v<_Tp, const void*>)
3175  return __u._M_ptr;
3176 #ifdef __SIZEOF_INT128__
3177  else if constexpr (is_same_v<_Tp, __int128>)
3178  return __u._M_i128;
3179  else if constexpr (is_same_v<_Tp, unsigned __int128>)
3180  return __u._M_u128;
3181 #endif
3182 #if _GLIBCXX_FORMAT_F128 == 2
3183  else if constexpr (is_same_v<_Tp, __float128_t>)
3184  return __u._M_f128;
3185 #endif
3186  else if constexpr (derived_from<_Tp, _HandleBase>)
3187  return static_cast<_Tp&>(__u._M_handle);
3188  // Otherwise, ill-formed.
3189  }
3190 
3191  template<typename _Tp>
3192  [[__gnu__::__always_inline__]]
3193  auto&
3194  _M_get() noexcept
3195  { return _S_get<_Tp>(*this); }
3196 
3197  template<typename _Tp>
3198  [[__gnu__::__always_inline__]]
3199  const auto&
3200  _M_get() const noexcept
3201  { return _S_get<_Tp>(*this); }
3202 
3203  template<typename _Tp>
3204  [[__gnu__::__always_inline__]]
3205  void
3206  _M_set(_Tp __v) noexcept
3207  {
3208  if constexpr (derived_from<_Tp, _HandleBase>)
3209  std::construct_at(&_M_handle, __v);
3210  else
3211  _S_get<_Tp>(*this) = __v;
3212  }
3213  };
3214 
3215  // [format.arg.store], class template format-arg-store
3216  template<typename _Context, typename... _Args>
3217  class _Arg_store;
3218 
3219 } // namespace __format
3220 /// @endcond
3221 
3222  template<typename _Context>
3223  class basic_format_arg
3224  {
3225  using _CharT = typename _Context::char_type;
3226 
3227  template<typename _Tp>
3228  static constexpr bool __formattable
3229  = __format::__formattable_with<_Tp, _Context>;
3230 
3231  public:
3232  class handle : public __format::_Arg_value<_Context>::_HandleBase
3233  {
3234  using _Base = typename __format::_Arg_value<_Context>::_HandleBase;
3235 
3236  // Format as const if possible, to reduce instantiations.
3237  template<typename _Tp>
3238  using __maybe_const_t
3239  = __conditional_t<__formattable<const _Tp>, const _Tp, _Tp>;
3240 
3241  template<typename _Tq>
3242  static void
3243  _S_format(basic_format_parse_context<_CharT>& __parse_ctx,
3244  _Context& __format_ctx, const void* __ptr)
3245  {
3246  using _Td = remove_const_t<_Tq>;
3247  typename _Context::template formatter_type<_Td> __f;
3248  __parse_ctx.advance_to(__f.parse(__parse_ctx));
3249  _Tq& __val = *const_cast<_Tq*>(static_cast<const _Td*>(__ptr));
3250  __format_ctx.advance_to(__f.format(__val, __format_ctx));
3251  }
3252 
3253  template<typename _Tp>
3254  explicit
3255  handle(_Tp& __val) noexcept
3256  {
3257  this->_M_ptr = __builtin_addressof(__val);
3258  auto __func = _S_format<__maybe_const_t<_Tp>>;
3259  this->_M_func = reinterpret_cast<void(*)()>(__func);
3260  }
3261 
3262  friend class basic_format_arg<_Context>;
3263 
3264  public:
3265  handle(const handle&) = default;
3266  handle& operator=(const handle&) = default;
3267 
3268  [[__gnu__::__always_inline__]]
3269  void
3270  format(basic_format_parse_context<_CharT>& __pc, _Context& __fc) const
3271  {
3272  using _Func = void(*)(basic_format_parse_context<_CharT>&,
3273  _Context&, const void*);
3274  auto __f = reinterpret_cast<_Func>(this->_M_func);
3275  __f(__pc, __fc, this->_M_ptr);
3276  }
3277  };
3278 
3279  [[__gnu__::__always_inline__]]
3280  basic_format_arg() noexcept : _M_type(__format::_Arg_none) { }
3281 
3282  [[nodiscard,__gnu__::__always_inline__]]
3283  explicit operator bool() const noexcept
3284  { return _M_type != __format::_Arg_none; }
3285 
3286  private:
3287  template<typename _Ctx>
3288  friend class basic_format_args;
3289 
3290  template<typename _Ctx, typename... _Args>
3291  friend class __format::_Arg_store;
3292 
3293  static_assert(is_trivially_copyable_v<__format::_Arg_value<_Context>>);
3294 
3295  __format::_Arg_value<_Context> _M_val;
3296  __format::_Arg_t _M_type;
3297 
3298  // Transform incoming argument type to the type stored in _Arg_value.
3299  // e.g. short -> int, std::string -> std::string_view,
3300  // char[3] -> const char*.
3301  template<typename _Tp>
3302  static consteval auto
3303  _S_to_arg_type()
3304  {
3305  using _Td = remove_const_t<_Tp>;
3306  if constexpr (is_same_v<_Td, bool>)
3307  return type_identity<bool>();
3308  else if constexpr (is_same_v<_Td, _CharT>)
3309  return type_identity<_CharT>();
3310  else if constexpr (is_same_v<_Td, char> && is_same_v<_CharT, wchar_t>)
3311  return type_identity<_CharT>();
3312 #ifdef __SIZEOF_INT128__ // Check before signed/unsigned integer
3313  else if constexpr (is_same_v<_Td, __int128>)
3314  return type_identity<__int128>();
3315  else if constexpr (is_same_v<_Td, unsigned __int128>)
3316  return type_identity<unsigned __int128>();
3317 #endif
3318  else if constexpr (__is_signed_integer<_Td>::value)
3319  {
3320  if constexpr (sizeof(_Td) <= sizeof(int))
3321  return type_identity<int>();
3322  else if constexpr (sizeof(_Td) <= sizeof(long long))
3323  return type_identity<long long>();
3324  }
3325  else if constexpr (__is_unsigned_integer<_Td>::value)
3326  {
3327  if constexpr (sizeof(_Td) <= sizeof(unsigned))
3328  return type_identity<unsigned>();
3329  else if constexpr (sizeof(_Td) <= sizeof(unsigned long long))
3330  return type_identity<unsigned long long>();
3331  }
3332  else if constexpr (is_same_v<_Td, float>)
3333  return type_identity<float>();
3334  else if constexpr (is_same_v<_Td, double>)
3335  return type_identity<double>();
3336 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3337  else if constexpr (is_same_v<_Td, long double>)
3338  return type_identity<long double>();
3339 #else
3340  else if constexpr (is_same_v<_Td, __ibm128>)
3341  return type_identity<__ibm128>();
3342  else if constexpr (is_same_v<_Td, __ieee128>)
3343  return type_identity<__ieee128>();
3344 #endif
3345 
3346 #if defined(__FLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
3347  else if constexpr (is_same_v<_Td, _Float16>)
3348  return type_identity<float>();
3349 #endif
3350 
3351 #if defined(__BFLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
3352  else if constexpr (is_same_v<_Td, decltype(0.0bf16)>)
3353  return type_identity<float>();
3354 #endif
3355 
3356 #ifdef __FLT32_DIG__
3357  else if constexpr (is_same_v<_Td, _Float32>)
3358 # ifdef _GLIBCXX_FLOAT_IS_IEEE_BINARY32
3359  return type_identity<float>();
3360 # else
3361  return type_identity<_Float32>();
3362 # endif
3363 #endif
3364 #ifdef __FLT64_DIG__
3365  else if constexpr (is_same_v<_Td, _Float64>)
3366 # ifdef _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
3367  return type_identity<double>();
3368 # else
3369  return type_identity<_Float64>();
3370 # endif
3371 #endif
3372 #if _GLIBCXX_FORMAT_F128
3373 # if __FLT128_DIG__
3374  else if constexpr (is_same_v<_Td, _Float128>)
3375  return type_identity<__format::__float128_t>();
3376 # endif
3377 # if __SIZEOF_FLOAT128__
3378  else if constexpr (is_same_v<_Td, __float128>)
3379  return type_identity<__format::__float128_t>();
3380 # endif
3381 #endif
3382  else if constexpr (__is_specialization_of<_Td, basic_string_view>
3383  || __is_specialization_of<_Td, basic_string>)
3384  {
3385  if constexpr (is_same_v<typename _Td::value_type, _CharT>)
3386  return type_identity<basic_string_view<_CharT>>();
3387  else
3388  return type_identity<handle>();
3389  }
3390  else if constexpr (is_same_v<decay_t<_Td>, const _CharT*>)
3391  return type_identity<const _CharT*>();
3392  else if constexpr (is_same_v<decay_t<_Td>, _CharT*>)
3393  return type_identity<const _CharT*>();
3394  else if constexpr (is_void_v<remove_pointer_t<_Td>>)
3395  return type_identity<const void*>();
3396  else if constexpr (is_same_v<_Td, nullptr_t>)
3397  return type_identity<const void*>();
3398  else
3399  return type_identity<handle>();
3400  }
3401 
3402  // Transform a formattable type to the appropriate storage type.
3403  template<typename _Tp>
3404  using _Normalize = typename decltype(_S_to_arg_type<_Tp>())::type;
3405 
3406  // Get the _Arg_t value corresponding to a normalized type.
3407  template<typename _Tp>
3408  static consteval __format::_Arg_t
3409  _S_to_enum()
3410  {
3411  using namespace __format;
3412  if constexpr (is_same_v<_Tp, bool>)
3413  return _Arg_bool;
3414  else if constexpr (is_same_v<_Tp, _CharT>)
3415  return _Arg_c;
3416  else if constexpr (is_same_v<_Tp, int>)
3417  return _Arg_i;
3418  else if constexpr (is_same_v<_Tp, unsigned>)
3419  return _Arg_u;
3420  else if constexpr (is_same_v<_Tp, long long>)
3421  return _Arg_ll;
3422  else if constexpr (is_same_v<_Tp, unsigned long long>)
3423  return _Arg_ull;
3424  else if constexpr (is_same_v<_Tp, float>)
3425  return _Arg_flt;
3426  else if constexpr (is_same_v<_Tp, double>)
3427  return _Arg_dbl;
3428 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3429  else if constexpr (is_same_v<_Tp, long double>)
3430  return _Arg_ldbl;
3431 #else
3432  // Don't use _Arg_ldbl for this target, it's ambiguous.
3433  else if constexpr (is_same_v<_Tp, __ibm128>)
3434  return _Arg_ibm128;
3435  else if constexpr (is_same_v<_Tp, __ieee128>)
3436  return _Arg_f128;
3437 #endif
3438  else if constexpr (is_same_v<_Tp, const _CharT*>)
3439  return _Arg_str;
3440  else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
3441  return _Arg_sv;
3442  else if constexpr (is_same_v<_Tp, const void*>)
3443  return _Arg_ptr;
3444 #ifdef __SIZEOF_INT128__
3445  else if constexpr (is_same_v<_Tp, __int128>)
3446  return _Arg_i128;
3447  else if constexpr (is_same_v<_Tp, unsigned __int128>)
3448  return _Arg_u128;
3449 #endif
3450 
3451  // N.B. some of these types will never actually be used here,
3452  // because they get normalized to a standard floating-point type.
3453 #if defined __FLT32_DIG__ && ! _GLIBCXX_FLOAT_IS_IEEE_BINARY32
3454  else if constexpr (is_same_v<_Tp, _Float32>)
3455  return _Arg_f32;
3456 #endif
3457 #if defined __FLT64_DIG__ && ! _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
3458  else if constexpr (is_same_v<_Tp, _Float64>)
3459  return _Arg_f64;
3460 #endif
3461 #if _GLIBCXX_FORMAT_F128 == 2
3462  else if constexpr (is_same_v<_Tp, __format::__float128_t>)
3463  return _Arg_f128;
3464 #endif
3465  else if constexpr (is_same_v<_Tp, handle>)
3466  return _Arg_handle;
3467  }
3468 
3469  template<typename _Tp>
3470  void
3471  _M_set(_Tp __v) noexcept
3472  {
3473  _M_type = _S_to_enum<_Tp>();
3474  _M_val._M_set(__v);
3475  }
3476 
3477  template<typename _Tp>
3478  requires __format::__formattable_with<_Tp, _Context>
3479  explicit
3480  basic_format_arg(_Tp& __v) noexcept
3481  {
3482  using _Td = _Normalize<_Tp>;
3483  if constexpr (is_same_v<_Td, basic_string_view<_CharT>>)
3484  _M_set(_Td{__v.data(), __v.size()});
3485  else if constexpr (is_same_v<remove_const_t<_Tp>, char>
3486  && is_same_v<_CharT, wchar_t>)
3487  _M_set(static_cast<_Td>(static_cast<unsigned char>(__v)));
3488  else
3489  _M_set(static_cast<_Td>(__v));
3490  }
3491 
3492  template<typename _Ctx, typename... _Argz>
3493  friend auto
3494  make_format_args(_Argz&...) noexcept;
3495 
3496  template<typename _Visitor, typename _Ctx>
3497  friend decltype(auto)
3498  visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx>);
3499 
3500  template<typename _Visitor>
3501  decltype(auto)
3502  _M_visit(_Visitor&& __vis, __format::_Arg_t __type)
3503  {
3504  using namespace __format;
3505  switch (__type)
3506  {
3507  case _Arg_none:
3508  return std::forward<_Visitor>(__vis)(_M_val._M_none);
3509  case _Arg_bool:
3510  return std::forward<_Visitor>(__vis)(_M_val._M_bool);
3511  case _Arg_c:
3512  return std::forward<_Visitor>(__vis)(_M_val._M_c);
3513  case _Arg_i:
3514  return std::forward<_Visitor>(__vis)(_M_val._M_i);
3515  case _Arg_u:
3516  return std::forward<_Visitor>(__vis)(_M_val._M_u);
3517  case _Arg_ll:
3518  return std::forward<_Visitor>(__vis)(_M_val._M_ll);
3519  case _Arg_ull:
3520  return std::forward<_Visitor>(__vis)(_M_val._M_ull);
3521 #if __glibcxx_to_chars // FIXME: need to be able to format these types!
3522  case _Arg_flt:
3523  return std::forward<_Visitor>(__vis)(_M_val._M_flt);
3524  case _Arg_dbl:
3525  return std::forward<_Visitor>(__vis)(_M_val._M_dbl);
3526 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3527  case _Arg_ldbl:
3528  return std::forward<_Visitor>(__vis)(_M_val._M_ldbl);
3529 #else
3530  case _Arg_f128:
3531  return std::forward<_Visitor>(__vis)(_M_val._M_f128);
3532  case _Arg_ibm128:
3533  return std::forward<_Visitor>(__vis)(_M_val._M_ibm128);
3534 #endif
3535 #endif
3536  case _Arg_str:
3537  return std::forward<_Visitor>(__vis)(_M_val._M_str);
3538  case _Arg_sv:
3539  return std::forward<_Visitor>(__vis)(_M_val._M_sv);
3540  case _Arg_ptr:
3541  return std::forward<_Visitor>(__vis)(_M_val._M_ptr);
3542  case _Arg_handle:
3543  {
3544  auto& __h = static_cast<handle&>(_M_val._M_handle);
3545  return std::forward<_Visitor>(__vis)(__h);
3546  }
3547 #ifdef __SIZEOF_INT128__
3548  case _Arg_i128:
3549  return std::forward<_Visitor>(__vis)(_M_val._M_i128);
3550  case _Arg_u128:
3551  return std::forward<_Visitor>(__vis)(_M_val._M_u128);
3552 #endif
3553 
3554 #if _GLIBCXX_FORMAT_F128 == 2
3555  case _Arg_f128:
3556  return std::forward<_Visitor>(__vis)(_M_val._M_f128);
3557 #endif
3558 
3559  default:
3560  // _Arg_f16 etc.
3561  __builtin_unreachable();
3562  }
3563  }
3564  };
3565 
3566  template<typename _Visitor, typename _Context>
3567  inline decltype(auto)
3568  visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
3569  {
3570  return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type);
3571  }
3572 
3573 /// @cond undocumented
3574 namespace __format
3575 {
3576  struct _WidthPrecVisitor
3577  {
3578  template<typename _Tp>
3579  size_t
3580  operator()(_Tp& __arg) const
3581  {
3582  if constexpr (is_same_v<_Tp, monostate>)
3583  __format::__invalid_arg_id_in_format_string();
3584  // _GLIBCXX_RESOLVE_LIB_DEFECTS
3585  // 3720. Restrict the valid types of arg-id for width and precision
3586  // 3721. Allow an arg-id with a value of zero for width
3587  else if constexpr (sizeof(_Tp) <= sizeof(long long))
3588  {
3589  // _GLIBCXX_RESOLVE_LIB_DEFECTS
3590  // 3720. Restrict the valid types of arg-id for width and precision
3591  if constexpr (__is_unsigned_integer<_Tp>::value)
3592  return __arg;
3593  else if constexpr (__is_signed_integer<_Tp>::value)
3594  if (__arg >= 0)
3595  return __arg;
3596  }
3597  __throw_format_error("format error: argument used for width or "
3598  "precision must be a non-negative integer");
3599  }
3600  };
3601 
3602  template<typename _Context>
3603  inline size_t
3604  __int_from_arg(const basic_format_arg<_Context>& __arg)
3605  { return std::visit_format_arg(_WidthPrecVisitor(), __arg); }
3606 
3607  // Pack _Arg_t enum values into a single 60-bit integer.
3608  template<int _Bits, size_t _Nm>
3609  constexpr auto
3610  __pack_arg_types(const array<_Arg_t, _Nm>& __types)
3611  {
3612  __UINT64_TYPE__ __packed_types = 0;
3613  for (auto __i = __types.rbegin(); __i != __types.rend(); ++__i)
3614  __packed_types = (__packed_types << _Bits) | *__i;
3615  return __packed_types;
3616  }
3617 } // namespace __format
3618 /// @endcond
3619 
3620  template<typename _Context>
3621  class basic_format_args
3622  {
3623  static constexpr int _S_packed_type_bits = 5; // _Arg_t values [0,20]
3624  static constexpr int _S_packed_type_mask = 0b11111;
3625  static constexpr int _S_max_packed_args = 12;
3626 
3627  static_assert( __format::_Arg_max_ <= (1 << _S_packed_type_bits) );
3628 
3629  template<typename... _Args>
3630  using _Store = __format::_Arg_store<_Context, _Args...>;
3631 
3632  template<typename _Ctx, typename... _Args>
3633  friend class __format::_Arg_store;
3634 
3635  using uint64_t = __UINT64_TYPE__;
3636  using _Format_arg = basic_format_arg<_Context>;
3637  using _Format_arg_val = __format::_Arg_value<_Context>;
3638 
3639  // If args are packed then the number of args is in _M_packed_size and
3640  // the packed types are in _M_unpacked_size, accessed via _M_type(i).
3641  // If args are not packed then the number of args is in _M_unpacked_size
3642  // and _M_packed_size is zero.
3643  uint64_t _M_packed_size : 4;
3644  uint64_t _M_unpacked_size : 60;
3645 
3646  union {
3647  const _Format_arg_val* _M_values; // Active when _M_packed_size != 0
3648  const _Format_arg* _M_args; // Active when _M_packed_size == 0
3649  };
3650 
3651  size_t
3652  _M_size() const noexcept
3653  { return _M_packed_size ? _M_packed_size : _M_unpacked_size; }
3654 
3655  typename __format::_Arg_t
3656  _M_type(size_t __i) const noexcept
3657  {
3658  uint64_t __t = _M_unpacked_size >> (__i * _S_packed_type_bits);
3659  return static_cast<__format::_Arg_t>(__t & _S_packed_type_mask);
3660  }
3661 
3662  template<typename _Ctx, typename... _Args>
3663  friend auto
3664  make_format_args(_Args&...) noexcept;
3665 
3666  // An array of _Arg_t enums corresponding to _Args...
3667  template<typename... _Args>
3668  static consteval array<__format::_Arg_t, sizeof...(_Args)>
3669  _S_types_to_pack()
3670  { return {_Format_arg::template _S_to_enum<_Args>()...}; }
3671 
3672  public:
3673  template<typename... _Args>
3674  basic_format_args(const _Store<_Args...>& __store) noexcept;
3675 
3676  [[nodiscard,__gnu__::__always_inline__]]
3677  basic_format_arg<_Context>
3678  get(size_t __i) const noexcept
3679  {
3680  basic_format_arg<_Context> __arg;
3681  if (__i < _M_packed_size)
3682  {
3683  __arg._M_type = _M_type(__i);
3684  __arg._M_val = _M_values[__i];
3685  }
3686  else if (_M_packed_size == 0 && __i < _M_unpacked_size)
3687  __arg = _M_args[__i];
3688  return __arg;
3689  }
3690  };
3691 
3692  // _GLIBCXX_RESOLVE_LIB_DEFECTS
3693  // 3810. CTAD for std::basic_format_args
3694  template<typename _Context, typename... _Args>
3695  basic_format_args(__format::_Arg_store<_Context, _Args...>)
3696  -> basic_format_args<_Context>;
3697 
3698  template<typename _Context, typename... _Args>
3699  auto
3700  make_format_args(_Args&... __fmt_args) noexcept;
3701 
3702  // An array of type-erased formatting arguments.
3703  template<typename _Context, typename... _Args>
3704  class __format::_Arg_store
3705  {
3706  friend std::basic_format_args<_Context>;
3707 
3708  template<typename _Ctx, typename... _Argz>
3709  friend auto std::
3710 #if _GLIBCXX_INLINE_VERSION
3711  __8:: // Needed for PR c++/59256
3712 #endif
3713  make_format_args(_Argz&...) noexcept;
3714 
3715  // For a sufficiently small number of arguments we only store values.
3716  // basic_format_args can get the types from the _Args pack.
3717  static constexpr bool _S_values_only
3718  = sizeof...(_Args) <= basic_format_args<_Context>::_S_max_packed_args;
3719 
3720  using _Element_t
3721  = __conditional_t<_S_values_only,
3722  __format::_Arg_value<_Context>,
3723  basic_format_arg<_Context>>;
3724 
3725  _Element_t _M_args[sizeof...(_Args)];
3726 
3727  template<typename _Tp>
3728  static _Element_t
3729  _S_make_elt(_Tp& __v)
3730  {
3731  using _Tq = remove_const_t<_Tp>;
3732  using _CharT = typename _Context::char_type;
3733  static_assert(is_default_constructible_v<formatter<_Tq, _CharT>>,
3734  "std::formatter must be specialized for the type "
3735  "of each format arg");
3736  using __format::__formattable_with;
3737  if constexpr (is_const_v<_Tp>)
3738  if constexpr (!__formattable_with<_Tp, _Context>)
3739  if constexpr (__formattable_with<_Tq, _Context>)
3740  static_assert(__formattable_with<_Tp, _Context>,
3741  "format arg must be non-const because its "
3742  "std::formatter specialization has a "
3743  "non-const reference parameter");
3744  basic_format_arg<_Context> __arg(__v);
3745  if constexpr (_S_values_only)
3746  return __arg._M_val;
3747  else
3748  return __arg;
3749  }
3750 
3751  template<typename... _Tp>
3752  requires (sizeof...(_Tp) == sizeof...(_Args))
3753  [[__gnu__::__always_inline__]]
3754  _Arg_store(_Tp&... __a) noexcept
3755  : _M_args{_S_make_elt(__a)...}
3756  { }
3757  };
3758 
3759  template<typename _Context>
3760  class __format::_Arg_store<_Context>
3761  { };
3762 
3763  template<typename _Context>
3764  template<typename... _Args>
3765  inline
3766  basic_format_args<_Context>::
3767  basic_format_args(const _Store<_Args...>& __store) noexcept
3768  {
3769  if constexpr (sizeof...(_Args) == 0)
3770  {
3771  _M_packed_size = 0;
3772  _M_unpacked_size = 0;
3773  _M_args = nullptr;
3774  }
3775  else if constexpr (sizeof...(_Args) <= _S_max_packed_args)
3776  {
3777  // The number of packed arguments:
3778  _M_packed_size = sizeof...(_Args);
3779  // The packed type enums:
3780  _M_unpacked_size
3781  = __format::__pack_arg_types<_S_packed_type_bits>(_S_types_to_pack<_Args...>());
3782  // The _Arg_value objects.
3783  _M_values = __store._M_args;
3784  }
3785  else
3786  {
3787  // No packed arguments:
3788  _M_packed_size = 0;
3789  // The number of unpacked arguments:
3790  _M_unpacked_size = sizeof...(_Args);
3791  // The basic_format_arg objects:
3792  _M_args = __store._M_args;
3793  }
3794  }
3795 
3796  /// Capture formatting arguments for use by `std::vformat`.
3797  template<typename _Context = format_context, typename... _Args>
3798  [[nodiscard,__gnu__::__always_inline__]]
3799  inline auto
3800  make_format_args(_Args&... __fmt_args) noexcept
3801  {
3802  using _Fmt_arg = basic_format_arg<_Context>;
3803  using _Store = __format::_Arg_store<_Context, typename _Fmt_arg::template
3804  _Normalize<_Args>...>;
3805  return _Store(__fmt_args...);
3806  }
3807 
3808 #ifdef _GLIBCXX_USE_WCHAR_T
3809  /// Capture formatting arguments for use by `std::vformat` (for wide output).
3810  template<typename... _Args>
3811  [[nodiscard,__gnu__::__always_inline__]]
3812  inline auto
3813  make_wformat_args(_Args&... __args) noexcept
3814  { return std::make_format_args<wformat_context>(__args...); }
3815 #endif
3816 
3817 /// @cond undocumented
3818 namespace __format
3819 {
3820  template<typename _Out, typename _CharT, typename _Context>
3821  _Out
3822  __do_vformat_to(_Out, basic_string_view<_CharT>,
3823  const basic_format_args<_Context>&,
3824  const locale* = nullptr);
3825 } // namespace __format
3826 /// @endcond
3827 
3828  /** Context for std::format and similar functions.
3829  *
3830  * A formatting context contains an output iterator and locale to use
3831  * for the formatting operations. Most programs will never need to use
3832  * this class template explicitly. For typical uses of `std::format` the
3833  * library will use the specializations `std::format_context` (for `char`)
3834  * and `std::wformat_context` (for `wchar_t`).
3835  */
3836  template<typename _Out, typename _CharT>
3837  class basic_format_context
3838  {
3839  static_assert( output_iterator<_Out, const _CharT&> );
3840 
3841  basic_format_args<basic_format_context> _M_args;
3842  _Out _M_out;
3843  __format::_Optional_locale _M_loc;
3844 
3845  basic_format_context(basic_format_args<basic_format_context> __args,
3846  _Out __out)
3847  : _M_args(__args), _M_out(std::move(__out))
3848  { }
3849 
3850  basic_format_context(basic_format_args<basic_format_context> __args,
3851  _Out __out, const std::locale& __loc)
3852  : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
3853  { }
3854 
3855  // _GLIBCXX_RESOLVE_LIB_DEFECTS
3856  // 4061. Should std::basic_format_context be
3857  // default-constructible/copyable/movable?
3858  basic_format_context(const basic_format_context&) = delete;
3859  basic_format_context& operator=(const basic_format_context&) = delete;
3860 
3861  template<typename _Out2, typename _CharT2, typename _Context2>
3862  friend _Out2
3863  __format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
3864  const basic_format_args<_Context2>&,
3865  const locale*);
3866 
3867  public:
3868  ~basic_format_context() = default;
3869 
3870  using iterator = _Out;
3871  using char_type = _CharT;
3872  template<typename _Tp>
3873  using formatter_type = formatter<_Tp, _CharT>;
3874 
3875  [[nodiscard]]
3876  basic_format_arg<basic_format_context>
3877  arg(size_t __id) const noexcept
3878  { return _M_args.get(__id); }
3879 
3880  [[nodiscard]]
3881  std::locale locale() { return _M_loc.value(); }
3882 
3883  [[nodiscard]]
3884  iterator out() { return std::move(_M_out); }
3885 
3886  void advance_to(iterator __it) { _M_out = std::move(__it); }
3887  };
3888 
3889 
3890 /// @cond undocumented
3891 namespace __format
3892 {
3893  // Abstract base class defining an interface for scanning format strings.
3894  // Scan the characters in a format string, dividing it up into strings of
3895  // ordinary characters, escape sequences, and replacement fields.
3896  // Call virtual functions for derived classes to parse format-specifiers
3897  // or write formatted output.
3898  template<typename _CharT>
3899  struct _Scanner
3900  {
3901  using iterator = typename basic_format_parse_context<_CharT>::iterator;
3902 
3903  basic_format_parse_context<_CharT> _M_pc;
3904 
3905  constexpr explicit
3906  _Scanner(basic_string_view<_CharT> __str, size_t __nargs = -1)
3907  : _M_pc(__str, __nargs)
3908  { }
3909 
3910  constexpr iterator begin() const noexcept { return _M_pc.begin(); }
3911  constexpr iterator end() const noexcept { return _M_pc.end(); }
3912 
3913  constexpr void
3914  _M_scan()
3915  {
3916  basic_string_view<_CharT> __fmt = _M_fmt_str();
3917 
3918  if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
3919  {
3920  _M_pc.advance_to(begin() + 1);
3921  _M_format_arg(_M_pc.next_arg_id());
3922  return;
3923  }
3924 
3925  size_t __lbr = __fmt.find('{');
3926  size_t __rbr = __fmt.find('}');
3927 
3928  while (__fmt.size())
3929  {
3930  auto __cmp = __lbr <=> __rbr;
3931  if (__cmp == 0)
3932  {
3933  _M_on_chars(end());
3934  _M_pc.advance_to(end());
3935  return;
3936  }
3937  else if (__cmp < 0)
3938  {
3939  if (__lbr + 1 == __fmt.size()
3940  || (__rbr == __fmt.npos && __fmt[__lbr + 1] != '{'))
3941  __format::__unmatched_left_brace_in_format_string();
3942  const bool __is_escape = __fmt[__lbr + 1] == '{';
3943  iterator __last = begin() + __lbr + int(__is_escape);
3944  _M_on_chars(__last);
3945  _M_pc.advance_to(__last + 1);
3946  __fmt = _M_fmt_str();
3947  if (__is_escape)
3948  {
3949  if (__rbr != __fmt.npos)
3950  __rbr -= __lbr + 2;
3951  __lbr = __fmt.find('{');
3952  }
3953  else
3954  {
3955  _M_on_replacement_field();
3956  __fmt = _M_fmt_str();
3957  __lbr = __fmt.find('{');
3958  __rbr = __fmt.find('}');
3959  }
3960  }
3961  else
3962  {
3963  if (++__rbr == __fmt.size() || __fmt[__rbr] != '}')
3964  __format::__unmatched_right_brace_in_format_string();
3965  iterator __last = begin() + __rbr;
3966  _M_on_chars(__last);
3967  _M_pc.advance_to(__last + 1);
3968  __fmt = _M_fmt_str();
3969  if (__lbr != __fmt.npos)
3970  __lbr -= __rbr + 1;
3971  __rbr = __fmt.find('}');
3972  }
3973  }
3974  }
3975 
3976  constexpr basic_string_view<_CharT>
3977  _M_fmt_str() const noexcept
3978  { return {begin(), end()}; }
3979 
3980  constexpr virtual void _M_on_chars(iterator) { }
3981 
3982  constexpr void _M_on_replacement_field()
3983  {
3984  auto __next = begin();
3985 
3986  size_t __id;
3987  if (*__next == '}')
3988  __id = _M_pc.next_arg_id();
3989  else if (*__next == ':')
3990  {
3991  __id = _M_pc.next_arg_id();
3992  _M_pc.advance_to(++__next);
3993  }
3994  else
3995  {
3996  auto [__i, __ptr] = __format::__parse_arg_id(begin(), end());
3997  if (!__ptr || !(*__ptr == '}' || *__ptr == ':'))
3998  __format::__invalid_arg_id_in_format_string();
3999  _M_pc.check_arg_id(__id = __i);
4000  if (*__ptr == ':')
4001  {
4002  _M_pc.advance_to(++__ptr);
4003  }
4004  else
4005  _M_pc.advance_to(__ptr);
4006  }
4007  _M_format_arg(__id);
4008  if (begin() == end() || *begin() != '}')
4009  __format::__unmatched_left_brace_in_format_string();
4010  _M_pc.advance_to(begin() + 1); // Move past '}'
4011  }
4012 
4013  constexpr virtual void _M_format_arg(size_t __id) = 0;
4014  };
4015 
4016  // Process a format string and format the arguments in the context.
4017  template<typename _Out, typename _CharT>
4018  class _Formatting_scanner : public _Scanner<_CharT>
4019  {
4020  public:
4021  _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
4022  basic_string_view<_CharT> __str)
4023  : _Scanner<_CharT>(__str), _M_fc(__fc)
4024  { }
4025 
4026  private:
4027  basic_format_context<_Out, _CharT>& _M_fc;
4028 
4029  using iterator = typename _Scanner<_CharT>::iterator;
4030 
4031  constexpr void
4032  _M_on_chars(iterator __last) override
4033  {
4034  basic_string_view<_CharT> __str(this->begin(), __last);
4035  _M_fc.advance_to(__format::__write(_M_fc.out(), __str));
4036  }
4037 
4038  constexpr void
4039  _M_format_arg(size_t __id) override
4040  {
4041  using _Context = basic_format_context<_Out, _CharT>;
4042  using handle = typename basic_format_arg<_Context>::handle;
4043 
4044  std::visit_format_arg([this](auto& __arg) {
4045  using _Type = remove_reference_t<decltype(__arg)>;
4046  using _Formatter = typename _Context::template formatter_type<_Type>;
4047  if constexpr (is_same_v<_Type, monostate>)
4048  __format::__invalid_arg_id_in_format_string();
4049  else if constexpr (is_same_v<_Type, handle>)
4050  __arg.format(this->_M_pc, this->_M_fc);
4051  else if constexpr (is_default_constructible_v<_Formatter>)
4052  {
4053  _Formatter __f;
4054  this->_M_pc.advance_to(__f.parse(this->_M_pc));
4055  this->_M_fc.advance_to(__f.format(__arg, this->_M_fc));
4056  }
4057  else
4058  static_assert(__format::__formattable_with<_Type, _Context>);
4059  }, _M_fc.arg(__id));
4060  }
4061  };
4062 
4063  // Validate a format string for Args.
4064  template<typename _CharT, typename... _Args>
4065  class _Checking_scanner : public _Scanner<_CharT>
4066  {
4067  static_assert(
4068  (is_default_constructible_v<formatter<_Args, _CharT>> && ...),
4069  "std::formatter must be specialized for each type being formatted");
4070 
4071  public:
4072  constexpr
4073  _Checking_scanner(basic_string_view<_CharT> __str)
4074  : _Scanner<_CharT>(__str, sizeof...(_Args))
4075  { }
4076 
4077  private:
4078  constexpr void
4079  _M_format_arg(size_t __id) override
4080  {
4081  if constexpr (sizeof...(_Args) != 0)
4082  {
4083  if (__id < sizeof...(_Args))
4084  {
4085  _M_parse_format_spec<_Args...>(__id);
4086  return;
4087  }
4088  }
4089  __builtin_unreachable();
4090  }
4091 
4092  template<typename _Tp, typename... _OtherArgs>
4093  constexpr void
4094  _M_parse_format_spec(size_t __id)
4095  {
4096  if (__id == 0)
4097  {
4098  formatter<_Tp, _CharT> __f;
4099  this->_M_pc.advance_to(__f.parse(this->_M_pc));
4100  }
4101  else if constexpr (sizeof...(_OtherArgs) != 0)
4102  _M_parse_format_spec<_OtherArgs...>(__id - 1);
4103  else
4104  __builtin_unreachable();
4105  }
4106  };
4107 
4108  template<typename _Out, typename _CharT, typename _Context>
4109  inline _Out
4110  __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
4111  const basic_format_args<_Context>& __args,
4112  const locale* __loc)
4113  {
4114  _Iter_sink<_CharT, _Out> __sink(std::move(__out));
4115  _Sink_iter<_CharT> __sink_out;
4116 
4117  if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
4118  __sink_out = __out; // Already a sink iterator, safe to use post-move.
4119  else
4120  __sink_out = __sink.out();
4121 
4122  if constexpr (is_same_v<_CharT, char>)
4123  // Fast path for "{}" format strings and simple format arg types.
4124  if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
4125  {
4126  bool __done = false;
4127  std::visit_format_arg([&](auto& __arg) {
4128  using _Tp = remove_cvref_t<decltype(__arg)>;
4129  if constexpr (is_same_v<_Tp, bool>)
4130  {
4131  size_t __len = 4 + !__arg;
4132  const char* __chars[] = { "false", "true" };
4133  if (auto __res = __sink_out._M_reserve(__len))
4134  {
4135  __builtin_memcpy(__res.get(), __chars[__arg], __len);
4136  __res._M_bump(__len);
4137  __done = true;
4138  }
4139  }
4140  else if constexpr (is_same_v<_Tp, char>)
4141  {
4142  if (auto __res = __sink_out._M_reserve(1))
4143  {
4144  *__res.get() = __arg;
4145  __res._M_bump(1);
4146  __done = true;
4147  }
4148  }
4149  else if constexpr (is_integral_v<_Tp>)
4150  {
4151  make_unsigned_t<_Tp> __uval;
4152  const bool __neg = __arg < 0;
4153  if (__neg)
4154  __uval = make_unsigned_t<_Tp>(~__arg) + 1u;
4155  else
4156  __uval = __arg;
4157  const auto __n = __detail::__to_chars_len(__uval);
4158  if (auto __res = __sink_out._M_reserve(__n + __neg))
4159  {
4160  auto __ptr = __res.get();
4161  *__ptr = '-';
4162  __detail::__to_chars_10_impl(__ptr + (int)__neg, __n,
4163  __uval);
4164  __res._M_bump(__n + __neg);
4165  __done = true;
4166  }
4167  }
4168  else if constexpr (is_convertible_v<_Tp, string_view>)
4169  {
4170  string_view __sv = __arg;
4171  if (auto __res = __sink_out._M_reserve(__sv.size()))
4172  {
4173  __builtin_memcpy(__res.get(), __sv.data(), __sv.size());
4174  __res._M_bump(__sv.size());
4175  __done = true;
4176  }
4177  }
4178  }, __args.get(0));
4179 
4180  if (__done)
4181  {
4182  if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
4183  return __sink_out;
4184  else
4185  return std::move(__sink)._M_finish().out;
4186  }
4187  }
4188 
4189  auto __ctx = __loc == nullptr
4190  ? _Context(__args, __sink_out)
4191  : _Context(__args, __sink_out, *__loc);
4192  _Formatting_scanner<_Sink_iter<_CharT>, _CharT> __scanner(__ctx, __fmt);
4193  __scanner._M_scan();
4194 
4195  if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
4196  return __ctx.out();
4197  else
4198  return std::move(__sink)._M_finish().out;
4199  }
4200 
4201 } // namespace __format
4202 /// @endcond
4203 
4204  template<typename _CharT, typename... _Args>
4205  template<typename _Tp>
4206  requires convertible_to<const _Tp&, basic_string_view<_CharT>>
4207  consteval
4208  basic_format_string<_CharT, _Args...>::
4209  basic_format_string(const _Tp& __s)
4210  : _M_str(__s)
4211  {
4212  __format::_Checking_scanner<_CharT, remove_cvref_t<_Args>...>
4213  __scanner(_M_str);
4214  __scanner._M_scan();
4215  }
4216 
4217  // [format.functions], formatting functions
4218 
4219  template<typename _Out> requires output_iterator<_Out, const char&>
4220  [[__gnu__::__always_inline__]]
4221  inline _Out
4222  vformat_to(_Out __out, string_view __fmt, format_args __args)
4223  { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
4224 
4225 #ifdef _GLIBCXX_USE_WCHAR_T
4226  template<typename _Out> requires output_iterator<_Out, const wchar_t&>
4227  [[__gnu__::__always_inline__]]
4228  inline _Out
4229  vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
4230  { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
4231 #endif
4232 
4233  template<typename _Out> requires output_iterator<_Out, const char&>
4234  [[__gnu__::__always_inline__]]
4235  inline _Out
4236  vformat_to(_Out __out, const locale& __loc, string_view __fmt,
4237  format_args __args)
4238  {
4239  return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
4240  }
4241 
4242 #ifdef _GLIBCXX_USE_WCHAR_T
4243  template<typename _Out> requires output_iterator<_Out, const wchar_t&>
4244  [[__gnu__::__always_inline__]]
4245  inline _Out
4246  vformat_to(_Out __out, const locale& __loc, wstring_view __fmt,
4247  wformat_args __args)
4248  {
4249  return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
4250  }
4251 #endif
4252 
4253  [[nodiscard]]
4254  inline string
4255  vformat(string_view __fmt, format_args __args)
4256  {
4257  __format::_Str_sink<char> __buf;
4258  std::vformat_to(__buf.out(), __fmt, __args);
4259  return std::move(__buf).get();
4260  }
4261 
4262 #ifdef _GLIBCXX_USE_WCHAR_T
4263  [[nodiscard]]
4264  inline wstring
4265  vformat(wstring_view __fmt, wformat_args __args)
4266  {
4267  __format::_Str_sink<wchar_t> __buf;
4268  std::vformat_to(__buf.out(), __fmt, __args);
4269  return std::move(__buf).get();
4270  }
4271 #endif
4272 
4273  [[nodiscard]]
4274  inline string
4275  vformat(const locale& __loc, string_view __fmt, format_args __args)
4276  {
4277  __format::_Str_sink<char> __buf;
4278  std::vformat_to(__buf.out(), __loc, __fmt, __args);
4279  return std::move(__buf).get();
4280  }
4281 
4282 #ifdef _GLIBCXX_USE_WCHAR_T
4283  [[nodiscard]]
4284  inline wstring
4285  vformat(const locale& __loc, wstring_view __fmt, wformat_args __args)
4286  {
4287  __format::_Str_sink<wchar_t> __buf;
4288  std::vformat_to(__buf.out(), __loc, __fmt, __args);
4289  return std::move(__buf).get();
4290  }
4291 #endif
4292 
4293  template<typename... _Args>
4294  [[nodiscard]]
4295  inline string
4296  format(format_string<_Args...> __fmt, _Args&&... __args)
4297  { return std::vformat(__fmt.get(), std::make_format_args(__args...)); }
4298 
4299 #ifdef _GLIBCXX_USE_WCHAR_T
4300  template<typename... _Args>
4301  [[nodiscard]]
4302  inline wstring
4303  format(wformat_string<_Args...> __fmt, _Args&&... __args)
4304  { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); }
4305 #endif
4306 
4307  template<typename... _Args>
4308  [[nodiscard]]
4309  inline string
4310  format(const locale& __loc, format_string<_Args...> __fmt,
4311  _Args&&... __args)
4312  {
4313  return std::vformat(__loc, __fmt.get(),
4314  std::make_format_args(__args...));
4315  }
4316 
4317 #ifdef _GLIBCXX_USE_WCHAR_T
4318  template<typename... _Args>
4319  [[nodiscard]]
4320  inline wstring
4321  format(const locale& __loc, wformat_string<_Args...> __fmt,
4322  _Args&&... __args)
4323  {
4324  return std::vformat(__loc, __fmt.get(),
4325  std::make_wformat_args(__args...));
4326  }
4327 #endif
4328 
4329  template<typename _Out, typename... _Args>
4330  requires output_iterator<_Out, const char&>
4331  inline _Out
4332  format_to(_Out __out, format_string<_Args...> __fmt, _Args&&... __args)
4333  {
4334  return std::vformat_to(std::move(__out), __fmt.get(),
4335  std::make_format_args(__args...));
4336  }
4337 
4338 #ifdef _GLIBCXX_USE_WCHAR_T
4339  template<typename _Out, typename... _Args>
4340  requires output_iterator<_Out, const wchar_t&>
4341  inline _Out
4342  format_to(_Out __out, wformat_string<_Args...> __fmt, _Args&&... __args)
4343  {
4344  return std::vformat_to(std::move(__out), __fmt.get(),
4345  std::make_wformat_args(__args...));
4346  }
4347 #endif
4348 
4349  template<typename _Out, typename... _Args>
4350  requires output_iterator<_Out, const char&>
4351  inline _Out
4352  format_to(_Out __out, const locale& __loc, format_string<_Args...> __fmt,
4353  _Args&&... __args)
4354  {
4355  return std::vformat_to(std::move(__out), __loc, __fmt.get(),
4356  std::make_format_args(__args...));
4357  }
4358 
4359 #ifdef _GLIBCXX_USE_WCHAR_T
4360  template<typename _Out, typename... _Args>
4361  requires output_iterator<_Out, const wchar_t&>
4362  inline _Out
4363  format_to(_Out __out, const locale& __loc, wformat_string<_Args...> __fmt,
4364  _Args&&... __args)
4365  {
4366  return std::vformat_to(std::move(__out), __loc, __fmt.get(),
4367  std::make_wformat_args(__args...));
4368  }
4369 #endif
4370 
4371  template<typename _Out, typename... _Args>
4372  requires output_iterator<_Out, const char&>
4373  inline format_to_n_result<_Out>
4374  format_to_n(_Out __out, iter_difference_t<_Out> __n,
4375  format_string<_Args...> __fmt, _Args&&... __args)
4376  {
4377  __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
4378  std::vformat_to(__sink.out(), __fmt.get(),
4379  std::make_format_args(__args...));
4380  return std::move(__sink)._M_finish();
4381  }
4382 
4383 #ifdef _GLIBCXX_USE_WCHAR_T
4384  template<typename _Out, typename... _Args>
4385  requires output_iterator<_Out, const wchar_t&>
4386  inline format_to_n_result<_Out>
4387  format_to_n(_Out __out, iter_difference_t<_Out> __n,
4388  wformat_string<_Args...> __fmt, _Args&&... __args)
4389  {
4390  __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
4391  std::vformat_to(__sink.out(), __fmt.get(),
4392  std::make_wformat_args(__args...));
4393  return std::move(__sink)._M_finish();
4394  }
4395 #endif
4396 
4397  template<typename _Out, typename... _Args>
4398  requires output_iterator<_Out, const char&>
4399  inline format_to_n_result<_Out>
4400  format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
4401  format_string<_Args...> __fmt, _Args&&... __args)
4402  {
4403  __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
4404  std::vformat_to(__sink.out(), __loc, __fmt.get(),
4405  std::make_format_args(__args...));
4406  return std::move(__sink)._M_finish();
4407  }
4408 
4409 #ifdef _GLIBCXX_USE_WCHAR_T
4410  template<typename _Out, typename... _Args>
4411  requires output_iterator<_Out, const wchar_t&>
4412  inline format_to_n_result<_Out>
4413  format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
4414  wformat_string<_Args...> __fmt, _Args&&... __args)
4415  {
4416  __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
4417  std::vformat_to(__sink.out(), __loc, __fmt.get(),
4418  std::make_wformat_args(__args...));
4419  return std::move(__sink)._M_finish();
4420  }
4421 #endif
4422 
4423 /// @cond undocumented
4424 namespace __format
4425 {
4426 #if 1
4427  template<typename _CharT>
4428  class _Counting_sink final : public _Iter_sink<_CharT, _CharT*>
4429  {
4430  public:
4431  _Counting_sink() : _Iter_sink<_CharT, _CharT*>(nullptr, 0) { }
4432 
4433  [[__gnu__::__always_inline__]]
4434  size_t
4435  count() const
4436  { return this->_M_count + this->_M_used().size(); }
4437  };
4438 #else
4439  template<typename _CharT>
4440  class _Counting_sink : public _Buf_sink<_CharT>
4441  {
4442  size_t _M_count = 0;
4443 
4444  void
4445  _M_overflow() override
4446  {
4447  if (!std::is_constant_evaluated())
4448  _M_count += this->_M_used().size();
4449  this->_M_rewind();
4450  }
4451 
4452  public:
4453  _Counting_sink() = default;
4454 
4455  [[__gnu__::__always_inline__]]
4456  size_t
4457  count() noexcept
4458  {
4459  _Counting_sink::_M_overflow();
4460  return _M_count;
4461  }
4462  };
4463 #endif
4464 } // namespace __format
4465 /// @endcond
4466 
4467  template<typename... _Args>
4468  [[nodiscard]]
4469  inline size_t
4470  formatted_size(format_string<_Args...> __fmt, _Args&&... __args)
4471  {
4472  __format::_Counting_sink<char> __buf;
4473  std::vformat_to(__buf.out(), __fmt.get(),
4474  std::make_format_args(__args...));
4475  return __buf.count();
4476  }
4477 
4478 #ifdef _GLIBCXX_USE_WCHAR_T
4479  template<typename... _Args>
4480  [[nodiscard]]
4481  inline size_t
4482  formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args)
4483  {
4484  __format::_Counting_sink<wchar_t> __buf;
4485  std::vformat_to(__buf.out(), __fmt.get(),
4486  std::make_wformat_args(__args...));
4487  return __buf.count();
4488  }
4489 #endif
4490 
4491  template<typename... _Args>
4492  [[nodiscard]]
4493  inline size_t
4494  formatted_size(const locale& __loc, format_string<_Args...> __fmt,
4495  _Args&&... __args)
4496  {
4497  __format::_Counting_sink<char> __buf;
4498  std::vformat_to(__buf.out(), __loc, __fmt.get(),
4499  std::make_format_args(__args...));
4500  return __buf.count();
4501  }
4502 
4503 #ifdef _GLIBCXX_USE_WCHAR_T
4504  template<typename... _Args>
4505  [[nodiscard]]
4506  inline size_t
4507  formatted_size(const locale& __loc, wformat_string<_Args...> __fmt,
4508  _Args&&... __args)
4509  {
4510  __format::_Counting_sink<wchar_t> __buf;
4511  std::vformat_to(__buf.out(), __loc, __fmt.get(),
4512  std::make_wformat_args(__args...));
4513  return __buf.count();
4514  }
4515 #endif
4516 
4517 #if __cpp_lib_format_ranges
4518  // [format.range], formatting of ranges
4519  // [format.range.fmtkind], variable template format_kind
4520  enum class range_format {
4521  disabled,
4522  map,
4523  set,
4524  sequence,
4525  string,
4526  debug_string
4527  };
4528 
4529  /// @cond undocumented
4530  template<typename _Rg>
4531  constexpr auto format_kind = not defined(format_kind<_Rg>);
4532 
4533  template<typename _Tp>
4534  consteval range_format
4535  __fmt_kind()
4536  {
4537  using _Ref = ranges::range_reference_t<_Tp>;
4538  if constexpr (is_same_v<remove_cvref_t<_Ref>, _Tp>)
4539  return range_format::disabled;
4540  else if constexpr (requires { typename _Tp::key_type; })
4541  {
4542  if constexpr (requires { typename _Tp::mapped_type; })
4543  {
4544  using _Up = remove_cvref_t<_Ref>;
4545  if constexpr (__is_pair<_Up>)
4546  return range_format::map;
4547  else if constexpr (__is_specialization_of<_Up, tuple>)
4548  if constexpr (tuple_size_v<_Up> == 2)
4549  return range_format::map;
4550  }
4551  return range_format::set;
4552  }
4553  else
4554  return range_format::sequence;
4555  }
4556  /// @endcond
4557 
4558  /// A constant determining how a range should be formatted.
4559  template<ranges::input_range _Rg> requires same_as<_Rg, remove_cvref_t<_Rg>>
4560  constexpr range_format format_kind<_Rg> = __fmt_kind<_Rg>();
4561 
4562  // [format.range.formatter], class template range_formatter
4563  template<typename _Tp, typename _CharT = char>
4564  requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
4565  class range_formatter; // TODO
4566 
4567 /// @cond undocumented
4568 namespace __format
4569 {
4570  // [format.range.fmtdef], class template range-default-formatter
4571  template<range_format _Kind, ranges::input_range _Rg, typename _CharT>
4572  struct __range_default_formatter; // TODO
4573 } // namespace __format
4574 /// @endcond
4575 
4576  // [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr],
4577  // specializations for maps, sets, and strings
4578  template<ranges::input_range _Rg, typename _CharT>
4579  requires (format_kind<_Rg> != range_format::disabled)
4580  && formattable<ranges::range_reference_t<_Rg>, _CharT>
4581  struct formatter<_Rg, _CharT>
4582  : __format::__range_default_formatter<format_kind<_Rg>, _Rg, _CharT>
4583  { };
4584 #endif // C++23 formatting ranges
4585 
4586 _GLIBCXX_END_NAMESPACE_VERSION
4587 } // namespace std
4588 #endif // __cpp_lib_format
4589 #endif // _GLIBCXX_FORMAT