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