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 #ifdef _GLIBCXX_SYSHDR
33 #pragma GCC system_header
34 #endif
35 
36 #include <bits/requires_hosted.h> // for std::string
37 
38 #define __glibcxx_want_format
39 #define __glibcxx_want_format_ranges
40 #define __glibcxx_want_format_uchar
41 #include <bits/version.h>
42 
43 #ifdef __cpp_lib_format // C++ >= 20 && HOSTED
44 
45 #include <array>
46 #include <charconv>
47 #include <concepts>
48 #include <limits>
49 #include <locale>
50 #include <optional>
51 #include <span>
52 #include <string_view>
53 #include <string>
54 #include <bits/monostate.h>
55 #include <bits/formatfwd.h>
56 #include <bits/ranges_base.h> // input_range, range_reference_t
57 #include <bits/ranges_util.h> // subrange
58 #include <bits/ranges_algobase.h> // ranges::copy
59 #include <bits/stl_iterator.h> // back_insert_iterator
60 #include <bits/stl_pair.h> // __is_pair
61 #include <bits/unicode.h> // __is_scalar_value, _Utf_view, etc.
62 #include <bits/utility.h> // tuple_size_v
63 #include <ext/numeric_traits.h> // __int_traits
64 
65 #if !__has_builtin(__builtin_toupper)
66 # include <cctype>
67 #endif
68 
69 #pragma GCC diagnostic push
70 #pragma GCC diagnostic ignored "-Wpedantic" // __int128
71 #pragma GCC diagnostic ignored "-Wc++23-extensions" // bf16
72 
73 namespace std _GLIBCXX_VISIBILITY(default)
74 {
75 _GLIBCXX_BEGIN_NAMESPACE_VERSION
76 
77  // [format.fmt.string], class template basic_format_string
78  template<typename _CharT, typename... _Args> struct basic_format_string;
79 
80 /// @cond undocumented
81 namespace __format
82 {
83  // STATICALLY-WIDEN, see C++20 [time.general]
84  // It doesn't matter for format strings (which can only be char or wchar_t)
85  // but this returns the narrow string for anything that isn't wchar_t. This
86  // is done because const char* can be inserted into any ostream type, and
87  // will be widened at runtime if necessary.
88  template<typename _CharT>
89  consteval auto
90  _Widen(const char* __narrow, const wchar_t* __wide)
91  {
92  if constexpr (is_same_v<_CharT, wchar_t>)
93  return __wide;
94  else
95  return __narrow;
96  }
97 #define _GLIBCXX_WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
98 #define _GLIBCXX_WIDEN(S) _GLIBCXX_WIDEN_(_CharT, S)
99 
100  // Size for stack located buffer
101  template<typename _CharT>
102  constexpr size_t __stackbuf_size = 32 * sizeof(void*) / sizeof(_CharT);
103 
104  // Type-erased character sinks.
105  template<typename _CharT> class _Sink;
106  template<typename _CharT> class _Fixedbuf_sink;
107  template<typename _Seq> class _Seq_sink;
108 
109  template<typename _CharT, typename _Alloc = allocator<_CharT>>
110  using _Str_sink
111  = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>;
112 
113  // template<typename _CharT, typename _Alloc = allocator<_CharT>>
114  // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>;
115 
116  // Output iterator that writes to a type-erase character sink.
117  template<typename _CharT>
118  class _Sink_iter;
119 
120  // An unspecified output iterator type used in the `formattable` concept.
121  template<typename _CharT>
122  struct _Iter_for
123  { using type = back_insert_iterator<basic_string<_CharT>>; };
124 
125  template<typename _CharT>
126  using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>;
127 
128  template<typename _CharT>
129  struct _Runtime_format_string
130  {
131  [[__gnu__::__always_inline__]]
132  _Runtime_format_string(basic_string_view<_CharT> __s) noexcept
133  : _M_str(__s) { }
134 
135  _Runtime_format_string(const _Runtime_format_string&) = delete;
136  void operator=(const _Runtime_format_string&) = delete;
137 
138  private:
139  basic_string_view<_CharT> _M_str;
140 
141  template<typename, typename...> friend struct std::basic_format_string;
142  };
143 
144 } // namespace __format
145 /// @endcond
146 
147  using format_context = __format::__format_context<char>;
148 #ifdef _GLIBCXX_USE_WCHAR_T
149  using wformat_context = __format::__format_context<wchar_t>;
150 #endif
151 
152  // [format.args], class template basic_format_args
153  template<typename _Context> class basic_format_args;
154  using format_args = basic_format_args<format_context>;
155 #ifdef _GLIBCXX_USE_WCHAR_T
156  using wformat_args = basic_format_args<wformat_context>;
157 #endif
158 
159  // [format.arguments], arguments
160  // [format.arg], class template basic_format_arg
161  template<typename _Context>
162  class basic_format_arg;
163 
164  /** A compile-time checked format string for the specified argument types.
165  *
166  * @since C++23 but available as an extension in C++20.
167  */
168  template<typename _CharT, typename... _Args>
169  struct basic_format_string
170  {
171  template<typename _Tp>
172  requires convertible_to<const _Tp&, basic_string_view<_CharT>>
173  consteval
174  basic_format_string(const _Tp& __s);
175 
176  [[__gnu__::__always_inline__]]
177  basic_format_string(__format::_Runtime_format_string<_CharT> __s) noexcept
178  : _M_str(__s._M_str)
179  { }
180 
181  [[__gnu__::__always_inline__]]
182  constexpr basic_string_view<_CharT>
183  get() const noexcept
184  { return _M_str; }
185 
186  private:
187  basic_string_view<_CharT> _M_str;
188  };
189 
190  template<typename... _Args>
191  using format_string = basic_format_string<char, type_identity_t<_Args>...>;
192 
193 #ifdef _GLIBCXX_USE_WCHAR_T
194  template<typename... _Args>
195  using wformat_string
196  = basic_format_string<wchar_t, type_identity_t<_Args>...>;
197 #endif
198 
199 #if __cpp_lib_format >= 202311L // >= C++26
200  [[__gnu__::__always_inline__]]
201  inline __format::_Runtime_format_string<char>
202  runtime_format(string_view __fmt) noexcept
203  { return __fmt; }
204 
205 #ifdef _GLIBCXX_USE_WCHAR_T
206  [[__gnu__::__always_inline__]]
207  inline __format::_Runtime_format_string<wchar_t>
208  runtime_format(wstring_view __fmt) noexcept
209  { return __fmt; }
210 #endif
211 #endif // C++26
212 
213  // [format.formatter], formatter
214 
215  /// The primary template of std::formatter is disabled.
216  template<typename _Tp, typename _CharT>
217  struct formatter
218  {
219  formatter() = delete; // No std::formatter specialization for this type.
220  formatter(const formatter&) = delete;
221  formatter& operator=(const formatter&) = delete;
222  };
223 
224  // [format.error], class format_error
225  class format_error : public runtime_error
226  {
227  public:
228  explicit format_error(const string& __what) : runtime_error(__what) { }
229  explicit format_error(const char* __what) : runtime_error(__what) { }
230  };
231 
232  /// @cond undocumented
233  [[noreturn]]
234  inline void
235  __throw_format_error(const char* __what)
236  { _GLIBCXX_THROW_OR_ABORT(format_error(__what)); }
237 
238 namespace __format
239 {
240  // XXX use named functions for each constexpr error?
241 
242  [[noreturn]]
243  inline void
244  __unmatched_left_brace_in_format_string()
245  { __throw_format_error("format error: unmatched '{' in format string"); }
246 
247  [[noreturn]]
248  inline void
249  __unmatched_right_brace_in_format_string()
250  { __throw_format_error("format error: unmatched '}' in format string"); }
251 
252  [[noreturn]]
253  inline void
254  __conflicting_indexing_in_format_string()
255  { __throw_format_error("format error: conflicting indexing style in format string"); }
256 
257  [[noreturn]]
258  inline void
259  __invalid_arg_id_in_format_string()
260  { __throw_format_error("format error: invalid arg-id in format string"); }
261 
262  [[noreturn]]
263  inline void
264  __failed_to_parse_format_spec()
265  { __throw_format_error("format error: failed to parse format-spec"); }
266 
267  template<typename _CharT> class _Scanner;
268 
269 } // namespace __format
270  /// @endcond
271 
272  // [format.parse.ctx], class template basic_format_parse_context
273  template<typename _CharT> class basic_format_parse_context;
274  using format_parse_context = basic_format_parse_context<char>;
275 #ifdef _GLIBCXX_USE_WCHAR_T
276  using wformat_parse_context = basic_format_parse_context<wchar_t>;
277 #endif
278 
279  template<typename _CharT>
280  class basic_format_parse_context
281  {
282  public:
283  using char_type = _CharT;
284  using const_iterator = typename basic_string_view<_CharT>::const_iterator;
285  using iterator = const_iterator;
286 
287  constexpr explicit
288  basic_format_parse_context(basic_string_view<_CharT> __fmt) noexcept
289  : _M_begin(__fmt.begin()), _M_end(__fmt.end())
290  { }
291 
292  basic_format_parse_context(const basic_format_parse_context&) = delete;
293  void operator=(const basic_format_parse_context&) = delete;
294 
295  constexpr const_iterator begin() const noexcept { return _M_begin; }
296  constexpr const_iterator end() const noexcept { return _M_end; }
297 
298  constexpr void
299  advance_to(const_iterator __it) noexcept
300  { _M_begin = __it; }
301 
302  constexpr size_t
303  next_arg_id()
304  {
305  if (_M_indexing == _Manual)
306  __format::__conflicting_indexing_in_format_string();
307  _M_indexing = _Auto;
308 
309  // _GLIBCXX_RESOLVE_LIB_DEFECTS
310  // 3825. Missing compile-time argument id check in next_arg_id
311  if (std::is_constant_evaluated())
312  if (_M_next_arg_id == _M_num_args)
313  __format::__invalid_arg_id_in_format_string();
314  return _M_next_arg_id++;
315  }
316 
317  constexpr void
318  check_arg_id(size_t __id)
319  {
320  if (_M_indexing == _Auto)
321  __format::__conflicting_indexing_in_format_string();
322  _M_indexing = _Manual;
323 
324  if (std::is_constant_evaluated())
325  if (__id >= _M_num_args)
326  __format::__invalid_arg_id_in_format_string();
327  }
328 
329 #if __cpp_lib_format >= 202305L
330  template<typename... _Ts>
331  constexpr void
332  check_dynamic_spec(size_t __id) noexcept
333  {
334  static_assert(__valid_types_for_check_dynamic_spec<_Ts...>(),
335  "template arguments for check_dynamic_spec<Ts...>(id) "
336  "must be unique and must be one of the allowed types");
337  if consteval {
338  __check_dynamic_spec<_Ts...>(__id);
339  }
340  }
341 
342  constexpr void
343  check_dynamic_spec_integral(size_t __id) noexcept
344  {
345  if consteval {
346  __check_dynamic_spec<int, unsigned, long long,
347  unsigned long long>(__id);
348  }
349  }
350 
351  constexpr void
352  check_dynamic_spec_string(size_t __id) noexcept
353  {
354  if consteval {
355  __check_dynamic_spec<const _CharT*, basic_string_view<_CharT>>(__id);
356  }
357  }
358 
359  private:
360  // True if _Tp occurs exactly once in _Ts.
361  template<typename _Tp, typename... _Ts>
362  static constexpr bool __once = (is_same_v<_Tp, _Ts> + ...) == 1;
363 
364  template<typename... _Ts>
365  consteval bool
366  __valid_types_for_check_dynamic_spec()
367  {
368  // _GLIBCXX_RESOLVE_LIB_DEFECTS
369  // 4142. check_dynamic_spec should require at least one type
370  if constexpr (sizeof...(_Ts) == 0)
371  return false;
372  else
373  {
374  // The types in Ts... are unique. Each type in Ts... is one of
375  // bool, char_type, int, unsigned int, long long int,
376  // unsigned long long int, float, double, long double,
377  // const char_type*, basic_string_view<char_type>, or const void*.
378  unsigned __sum
379  = __once<bool, _Ts...>
380  + __once<char_type, _Ts...>
381  + __once<int, _Ts...>
382  + __once<unsigned int, _Ts...>
383  + __once<long long int, _Ts...>
384  + __once<unsigned long long int, _Ts...>
385  + __once<float, _Ts...>
386  + __once<double, _Ts...>
387  + __once<long double, _Ts...>
388  + __once<const char_type*, _Ts...>
389  + __once<basic_string_view<char_type>, _Ts...>
390  + __once<const void*, _Ts...>;
391  return __sum == sizeof...(_Ts);
392  }
393  }
394 
395  template<typename... _Ts>
396  consteval void
397  __check_dynamic_spec(size_t __id) noexcept;
398 
399  // This must not be constexpr.
400  static void __invalid_dynamic_spec(const char*);
401 
402  friend __format::_Scanner<_CharT>;
403 #endif
404 
405  // This constructor should only be used by the implementation.
406  constexpr explicit
407  basic_format_parse_context(basic_string_view<_CharT> __fmt,
408  size_t __num_args) noexcept
409  : _M_begin(__fmt.begin()), _M_end(__fmt.end()), _M_num_args(__num_args)
410  { }
411 
412  private:
413  iterator _M_begin;
414  iterator _M_end;
415  enum _Indexing { _Unknown, _Manual, _Auto };
416  _Indexing _M_indexing = _Unknown;
417  size_t _M_next_arg_id = 0;
418  size_t _M_num_args = 0;
419  };
420 
421 /// @cond undocumented
422  template<typename _Tp, template<typename...> class _Class>
423  constexpr bool __is_specialization_of = false;
424  template<template<typename...> class _Class, typename... _Args>
425  constexpr bool __is_specialization_of<_Class<_Args...>, _Class> = true;
426 
427 namespace __format
428 {
429  // pre: first != last
430  template<typename _CharT>
431  constexpr pair<unsigned short, const _CharT*>
432  __parse_integer(const _CharT* __first, const _CharT* __last)
433  {
434  if (__first == __last)
435  __builtin_unreachable();
436 
437  if constexpr (is_same_v<_CharT, char>)
438  {
439  const auto __start = __first;
440  unsigned short __val = 0;
441  // N.B. std::from_chars is not constexpr in C++20.
442  if (__detail::__from_chars_alnum<true>(__first, __last, __val, 10)
443  && __first != __start) [[likely]]
444  return {__val, __first};
445  }
446  else
447  {
448  constexpr int __n = 32;
449  char __buf[__n]{};
450  for (int __i = 0; __i < __n && (__first + __i) != __last; ++__i)
451  __buf[__i] = __first[__i];
452  auto [__v, __ptr] = __format::__parse_integer(__buf, __buf + __n);
453  if (__ptr) [[likely]]
454  return {__v, __first + (__ptr - __buf)};
455  }
456  return {0, nullptr};
457  }
458 
459  template<typename _CharT>
460  constexpr pair<unsigned short, const _CharT*>
461  __parse_arg_id(const _CharT* __first, const _CharT* __last)
462  {
463  if (__first == __last)
464  __builtin_unreachable();
465 
466  if (*__first == '0')
467  return {0, __first + 1}; // No leading zeros allowed, so '0...' == 0
468 
469  if ('1' <= *__first && *__first <= '9')
470  {
471  const unsigned short __id = *__first - '0';
472  const auto __next = __first + 1;
473  // Optimize for most likely case of single digit arg-id.
474  if (__next == __last || !('0' <= *__next && *__next <= '9'))
475  return {__id, __next};
476  else
477  return __format::__parse_integer(__first, __last);
478  }
479  return {0, nullptr};
480  }
481 
482  enum _Pres_type {
483  _Pres_none = 0, // Default type (not valid for integer presentation types).
484  // Presentation types for integral types (including bool and charT).
485  _Pres_d = 1, _Pres_b, _Pres_B, _Pres_o, _Pres_x, _Pres_X, _Pres_c,
486  // Presentation types for floating-point types.
487  _Pres_a = 1, _Pres_A, _Pres_e, _Pres_E, _Pres_f, _Pres_F, _Pres_g, _Pres_G,
488  _Pres_p = 0, _Pres_P, // For pointers.
489  _Pres_s = 0, // For strings, bool
490  _Pres_seq = 0, _Pres_str, // For ranges
491  _Pres_esc = 0xf, // For strings, charT and ranges
492  };
493 
494  enum _Align {
495  _Align_default,
496  _Align_left,
497  _Align_right,
498  _Align_centre,
499  };
500 
501  enum _Sign {
502  _Sign_default,
503  _Sign_plus,
504  _Sign_minus, // XXX does this need to be distinct from _Sign_default?
505  _Sign_space,
506  };
507 
508  enum _WidthPrec {
509  _WP_none, // No width/prec specified.
510  _WP_value, // Fixed width/prec specified.
511  _WP_from_arg // Use a formatting argument for width/prec.
512  };
513 
514  template<typename _Context>
515  size_t
516  __int_from_arg(const basic_format_arg<_Context>& __arg);
517 
518  constexpr bool __is_digit(char __c)
519  { return std::__detail::__from_chars_alnum_to_val(__c) < 10; }
520 
521  constexpr bool __is_xdigit(char __c)
522  { return std::__detail::__from_chars_alnum_to_val(__c) < 16; }
523 
524  template<typename _CharT>
525  struct _Spec
526  {
527  _Align _M_align : 2;
528  _Sign _M_sign : 2;
529  unsigned _M_alt : 1;
530  unsigned _M_localized : 1;
531  unsigned _M_zero_fill : 1;
532  _WidthPrec _M_width_kind : 2;
533  _WidthPrec _M_prec_kind : 2;
534  _Pres_type _M_type : 4;
535  unsigned _M_reserved : 1;
536  unsigned _M_reserved2 : 16;
537  unsigned short _M_width;
538  unsigned short _M_prec;
539  char32_t _M_fill = ' ';
540 
541  using iterator = typename basic_string_view<_CharT>::iterator;
542 
543  static constexpr _Align
544  _S_align(_CharT __c) noexcept
545  {
546  switch (__c)
547  {
548  case '<': return _Align_left;
549  case '>': return _Align_right;
550  case '^': return _Align_centre;
551  default: return _Align_default;
552  }
553  }
554 
555  // pre: __first != __last
556  constexpr iterator
557  _M_parse_fill_and_align(iterator __first, iterator __last) noexcept
558  { return _M_parse_fill_and_align(__first, __last, "{"); }
559 
560  // pre: __first != __last
561  constexpr iterator
562  _M_parse_fill_and_align(iterator __first, iterator __last, string_view __not_fill) noexcept
563  {
564  for (char __c : __not_fill)
565  if (*__first == static_cast<_CharT>(__c))
566  return __first;
567 
568  using namespace __unicode;
569  if constexpr (__literal_encoding_is_unicode<_CharT>())
570  {
571  // Accept any UCS scalar value as fill character.
572  _Utf32_view<ranges::subrange<iterator>> __uv({__first, __last});
573  if (!__uv.empty())
574  {
575  auto __beg = __uv.begin();
576  char32_t __c = *__beg++;
577  if (__is_scalar_value(__c))
578  if (auto __next = __beg.base(); __next != __last)
579  if (_Align __align = _S_align(*__next))
580  {
581  _M_fill = __c;
582  _M_align = __align;
583  return ++__next;
584  }
585  }
586  }
587  else if (__last - __first >= 2)
588  if (_Align __align = _S_align(__first[1]))
589  {
590  _M_fill = *__first;
591  _M_align = __align;
592  return __first + 2;
593  }
594 
595  if (_Align __align = _S_align(__first[0]))
596  {
597  _M_fill = ' ';
598  _M_align = __align;
599  return __first + 1;
600  }
601  return __first;
602  }
603 
604  static constexpr _Sign
605  _S_sign(_CharT __c) noexcept
606  {
607  switch (__c)
608  {
609  case '+': return _Sign_plus;
610  case '-': return _Sign_minus;
611  case ' ': return _Sign_space;
612  default: return _Sign_default;
613  }
614  }
615 
616  // pre: __first != __last
617  constexpr iterator
618  _M_parse_sign(iterator __first, iterator) noexcept
619  {
620  if (_Sign __sign = _S_sign(*__first))
621  {
622  _M_sign = __sign;
623  return __first + 1;
624  }
625  return __first;
626  }
627 
628  // pre: *__first is valid
629  constexpr iterator
630  _M_parse_alternate_form(iterator __first, iterator) noexcept
631  {
632  if (*__first == '#')
633  {
634  _M_alt = true;
635  ++__first;
636  }
637  return __first;
638  }
639 
640  // pre: __first != __last
641  constexpr iterator
642  _M_parse_zero_fill(iterator __first, iterator /* __last */) noexcept
643  {
644  if (*__first == '0')
645  {
646  _M_zero_fill = true;
647  ++__first;
648  }
649  return __first;
650  }
651 
652  // pre: __first != __last
653  static constexpr iterator
654  _S_parse_width_or_precision(iterator __first, iterator __last,
655  unsigned short& __val, bool& __arg_id,
656  basic_format_parse_context<_CharT>& __pc)
657  {
658  if (__format::__is_digit(*__first))
659  {
660  auto [__v, __ptr] = __format::__parse_integer(__first, __last);
661  if (!__ptr)
662  __throw_format_error("format error: invalid width or precision "
663  "in format-spec");
664  __first = __ptr;
665  __val = __v;
666  }
667  else if (*__first == '{')
668  {
669  __arg_id = true;
670  ++__first;
671  if (__first == __last)
672  __format::__unmatched_left_brace_in_format_string();
673  if (*__first == '}')
674  __val = __pc.next_arg_id();
675  else
676  {
677  auto [__v, __ptr] = __format::__parse_arg_id(__first, __last);
678  if (__ptr == nullptr || __ptr == __last || *__ptr != '}')
679  __format::__invalid_arg_id_in_format_string();
680  __first = __ptr;
681  __pc.check_arg_id(__v);
682  __val = __v;
683  }
684 #if __cpp_lib_format >= 202305L
685  __pc.check_dynamic_spec_integral(__val);
686 #endif
687  ++__first; // past the '}'
688  }
689  return __first;
690  }
691 
692  // pre: __first != __last
693  constexpr iterator
694  _M_parse_width(iterator __first, iterator __last,
695  basic_format_parse_context<_CharT>& __pc)
696  {
697  bool __arg_id = false;
698  if (*__first == '0')
699  __throw_format_error("format error: width must be non-zero in "
700  "format string");
701  auto __next = _S_parse_width_or_precision(__first, __last, _M_width,
702  __arg_id, __pc);
703  if (__next != __first)
704  _M_width_kind = __arg_id ? _WP_from_arg : _WP_value;
705  return __next;
706  }
707 
708  // pre: __first != __last
709  constexpr iterator
710  _M_parse_precision(iterator __first, iterator __last,
711  basic_format_parse_context<_CharT>& __pc)
712  {
713  if (__first[0] != '.')
714  return __first;
715 
716  iterator __next = ++__first;
717  bool __arg_id = false;
718  if (__next != __last)
719  __next = _S_parse_width_or_precision(__first, __last, _M_prec,
720  __arg_id, __pc);
721  if (__next == __first)
722  __throw_format_error("format error: missing precision after '.' in "
723  "format string");
724  _M_prec_kind = __arg_id ? _WP_from_arg : _WP_value;
725  return __next;
726  }
727 
728  // pre: __first != __last
729  constexpr iterator
730  _M_parse_locale(iterator __first, iterator /* __last */) noexcept
731  {
732  if (*__first == 'L')
733  {
734  _M_localized = true;
735  ++__first;
736  }
737  return __first;
738  }
739 
740  template<typename _Context>
741  size_t
742  _M_get_width(_Context& __ctx) const
743  {
744  size_t __width = 0;
745  if (_M_width_kind == _WP_value)
746  __width = _M_width;
747  else if (_M_width_kind == _WP_from_arg)
748  __width = __format::__int_from_arg(__ctx.arg(_M_width));
749  return __width;
750  }
751 
752  template<typename _Context>
753  size_t
754  _M_get_precision(_Context& __ctx) const
755  {
756  size_t __prec = -1;
757  if (_M_prec_kind == _WP_value)
758  __prec = _M_prec;
759  else if (_M_prec_kind == _WP_from_arg)
760  __prec = __format::__int_from_arg(__ctx.arg(_M_prec));
761  return __prec;
762  }
763  };
764 
765  template<typename _Int>
766  inline char*
767  __put_sign(_Int __i, _Sign __sign, char* __dest) noexcept
768  {
769  if (__i < 0)
770  *__dest = '-';
771  else if (__sign == _Sign_plus)
772  *__dest = '+';
773  else if (__sign == _Sign_space)
774  *__dest = ' ';
775  else
776  ++__dest;
777  return __dest;
778  }
779 
780  // Write STR to OUT (and do so efficiently if OUT is a _Sink_iter).
781  template<typename _Out, typename _CharT>
782  requires output_iterator<_Out, const _CharT&>
783  inline _Out
784  __write(_Out __out, basic_string_view<_CharT> __str)
785  {
786  if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
787  {
788  if (__str.size())
789  __out = __str;
790  }
791  else
792  for (_CharT __c : __str)
793  *__out++ = __c;
794  return __out;
795  }
796 
797  // Write STR to OUT with NFILL copies of FILL_CHAR specified by ALIGN.
798  // pre: __align != _Align_default
799  template<typename _Out, typename _CharT>
800  _Out
801  __write_padded(_Out __out, basic_string_view<_CharT> __str,
802  _Align __align, size_t __nfill, char32_t __fill_char)
803  {
804  const size_t __buflen = 0x20;
805  _CharT __padding_chars[__buflen];
806  __padding_chars[0] = _CharT();
807  basic_string_view<_CharT> __padding{__padding_chars, __buflen};
808 
809  auto __pad = [&__padding] (size_t __n, _Out& __o) {
810  if (__n == 0)
811  return;
812  while (__n > __padding.size())
813  {
814  __o = __format::__write(std::move(__o), __padding);
815  __n -= __padding.size();
816  }
817  if (__n != 0)
818  __o = __format::__write(std::move(__o), __padding.substr(0, __n));
819  };
820 
821  size_t __l, __r, __max;
822  if (__align == _Align_centre)
823  {
824  __l = __nfill / 2;
825  __r = __l + (__nfill & 1);
826  __max = __r;
827  }
828  else if (__align == _Align_right)
829  {
830  __l = __nfill;
831  __r = 0;
832  __max = __l;
833  }
834  else
835  {
836  __l = 0;
837  __r = __nfill;
838  __max = __r;
839  }
840 
841  using namespace __unicode;
842  if constexpr (__literal_encoding_is_unicode<_CharT>())
843  if (!__is_single_code_unit<_CharT>(__fill_char)) [[unlikely]]
844  {
845  // Encode fill char as multiple code units of type _CharT.
846  const char32_t __arr[1]{ __fill_char };
847  _Utf_view<_CharT, const char32_t(&)[1]> __v(__arr);
848  basic_string<_CharT> __padstr(__v.begin(), __v.end());
849  __padding = __padstr;
850  while (__l-- > 0)
851  __out = __format::__write(std::move(__out), __padding);
852  __out = __format::__write(std::move(__out), __str);
853  while (__r-- > 0)
854  __out = __format::__write(std::move(__out), __padding);
855  return __out;
856  }
857 
858  if (__max < __buflen)
859  __padding.remove_suffix(__buflen - __max);
860  else
861  __max = __buflen;
862 
863  char_traits<_CharT>::assign(__padding_chars, __max, __fill_char);
864  __pad(__l, __out);
865  __out = __format::__write(std::move(__out), __str);
866  __pad(__r, __out);
867 
868  return __out;
869  }
870 
871  // Write STR to OUT, with alignment and padding as determined by SPEC.
872  // pre: __spec._M_align != _Align_default || __align != _Align_default
873  template<typename _CharT, typename _Out>
874  _Out
875  __write_padded_as_spec(basic_string_view<type_identity_t<_CharT>> __str,
876  size_t __estimated_width,
877  basic_format_context<_Out, _CharT>& __fc,
878  const _Spec<_CharT>& __spec,
879  _Align __align = _Align_left)
880  {
881  size_t __width = __spec._M_get_width(__fc);
882 
883  if (__width <= __estimated_width)
884  return __format::__write(__fc.out(), __str);
885 
886  const size_t __nfill = __width - __estimated_width;
887 
888  if (__spec._M_align)
889  __align = __spec._M_align;
890 
891  return __format::__write_padded(__fc.out(), __str, __align, __nfill,
892  __spec._M_fill);
893  }
894 
895  // Values are indices into _Escapes::all.
896  enum class _Term_char : unsigned char {
897  _Tc_quote = 12,
898  _Tc_apos = 15
899  };
900 
901  template<typename _CharT>
902  struct _Escapes
903  {
904  using _Str_view = basic_string_view<_CharT>;
905 
906  static consteval
907  _Str_view _S_all()
908  { return _GLIBCXX_WIDEN("\t\\t\n\\n\r\\r\\\\\\\"\\\"'\\'\\u\\x"); }
909 
910  static constexpr
911  _CharT _S_term(_Term_char __term)
912  { return _S_all()[static_cast<unsigned char>(__term)]; }
913 
914  static consteval
915  _Str_view _S_tab()
916  { return _S_all().substr(0, 3); }
917 
918  static consteval
919  _Str_view _S_newline()
920  { return _S_all().substr(3, 3); }
921 
922  static consteval
923  _Str_view _S_return()
924  { return _S_all().substr(6, 3); }
925 
926  static consteval
927  _Str_view _S_bslash()
928  { return _S_all().substr(9, 3); }
929 
930  static consteval
931  _Str_view _S_quote()
932  { return _S_all().substr(12, 3); }
933 
934  static consteval
935  _Str_view _S_apos()
936  { return _S_all().substr(15, 3); }
937 
938  static consteval
939  _Str_view _S_u()
940  { return _S_all().substr(18, 2); }
941 
942  static consteval
943  _Str_view _S_x()
944  { return _S_all().substr(20, 2); }
945  };
946 
947  template<typename _CharT>
948  struct _Separators
949  {
950  using _Str_view = basic_string_view<_CharT>;
951 
952  static consteval
953  _Str_view _S_all()
954  { return _GLIBCXX_WIDEN("[]{}(), : "); }
955 
956  static consteval
957  _Str_view _S_squares()
958  { return _S_all().substr(0, 2); }
959 
960  static consteval
961  _Str_view _S_braces()
962  { return _S_all().substr(2, 2); }
963 
964  static consteval
965  _Str_view _S_parens()
966  { return _S_all().substr(4, 2); }
967 
968  static consteval
969  _Str_view _S_comma()
970  { return _S_all().substr(6, 2); }
971 
972  static consteval
973  _Str_view _S_colon()
974  { return _S_all().substr(8, 2); }
975  };
976 
977  template<typename _CharT>
978  constexpr bool __should_escape_ascii(_CharT __c, _Term_char __term)
979  {
980  using _Esc = _Escapes<_CharT>;
981  switch (__c)
982  {
983  case _Esc::_S_tab()[0]:
984  case _Esc::_S_newline()[0]:
985  case _Esc::_S_return()[0]:
986  case _Esc::_S_bslash()[0]:
987  return true;
988  case _Esc::_S_quote()[0]:
989  return __term == _Term_char::_Tc_quote;
990  case _Esc::_S_apos()[0]:
991  return __term == _Term_char::_Tc_apos;
992  default:
993  return (__c >= 0 && __c < 0x20) || __c == 0x7f;
994  };
995  }
996 
997  // @pre __c <= 0x10FFFF
998  constexpr bool __should_escape_unicode(char32_t __c, bool __prev_esc)
999  {
1000  if (__unicode::__should_escape_category(__c))
1001  return __c != U' ';
1002  if (!__prev_esc)
1003  return false;
1004  return __unicode::__grapheme_cluster_break_property(__c)
1005  == __unicode::_Gcb_property::_Gcb_Extend;
1006  }
1007 
1008  using uint_least32_t = __UINT_LEAST32_TYPE__;
1009  template<typename _Out, typename _CharT>
1010  _Out
1011  __write_escape_seq(_Out __out, uint_least32_t __val,
1012  basic_string_view<_CharT> __prefix)
1013  {
1014  using _Str_view = basic_string_view<_CharT>;
1015  constexpr size_t __max = 8;
1016  char __buf[__max];
1017  const string_view __narrow(
1018  __buf,
1019  std::__to_chars_i<uint_least32_t>(__buf, __buf + __max, __val, 16).ptr);
1020 
1021  __out = __format::__write(__out, __prefix);
1022  *__out = _Separators<_CharT>::_S_braces()[0];
1023  ++__out;
1024  if constexpr (is_same_v<char, _CharT>)
1025  __out = __format::__write(__out, __narrow);
1026 #ifdef _GLIBCXX_USE_WCHAR_T
1027  else
1028  {
1029  _CharT __wbuf[__max];
1030  const size_t __n = __narrow.size();
1031  std::__to_wstring_numeric(__narrow.data(), __n, __wbuf);
1032  __out = __format::__write(__out, _Str_view(__wbuf, __n));
1033  }
1034 #endif
1035  *__out = _Separators<_CharT>::_S_braces()[1];
1036  return ++__out;
1037  }
1038 
1039  template<typename _Out, typename _CharT>
1040  _Out
1041  __write_escaped_char(_Out __out, _CharT __c)
1042  {
1043  using _UChar = make_unsigned_t<_CharT>;
1044  using _Esc = _Escapes<_CharT>;
1045  switch (__c)
1046  {
1047  case _Esc::_S_tab()[0]:
1048  return __format::__write(__out, _Esc::_S_tab().substr(1, 2));
1049  case _Esc::_S_newline()[0]:
1050  return __format::__write(__out, _Esc::_S_newline().substr(1, 2));
1051  case _Esc::_S_return()[0]:
1052  return __format::__write(__out, _Esc::_S_return().substr(1, 2));
1053  case _Esc::_S_bslash()[0]:
1054  return __format::__write(__out, _Esc::_S_bslash().substr(1, 2));
1055  case _Esc::_S_quote()[0]:
1056  return __format::__write(__out, _Esc::_S_quote().substr(1, 2));
1057  case _Esc::_S_apos()[0]:
1058  return __format::__write(__out, _Esc::_S_apos().substr(1, 2));
1059  default:
1060  return __format::__write_escape_seq(__out,
1061  static_cast<_UChar>(__c),
1062  _Esc::_S_u());
1063  }
1064  }
1065 
1066  template<typename _CharT, typename _Out>
1067  _Out
1068  __write_escaped_ascii(_Out __out,
1069  basic_string_view<_CharT> __str,
1070  _Term_char __term)
1071  {
1072  using _Str_view = basic_string_view<_CharT>;
1073  auto __first = __str.begin();
1074  auto const __last = __str.end();
1075  while (__first != __last)
1076  {
1077  auto __print = __first;
1078  // assume anything outside ASCII is printable
1079  while (__print != __last
1080  && !__format::__should_escape_ascii(*__print, __term))
1081  ++__print;
1082 
1083  if (__print != __first)
1084  __out = __format::__write(__out, _Str_view(__first, __print));
1085 
1086  if (__print == __last)
1087  return __out;
1088 
1089  __first = __print;
1090  __out = __format::__write_escaped_char(__out, *__first);
1091  ++__first;
1092  }
1093  return __out;
1094  }
1095 
1096  template<typename _CharT, typename _Out>
1097  _Out
1098  __write_escaped_unicode(_Out __out,
1099  basic_string_view<_CharT> __str,
1100  _Term_char __term)
1101  {
1102  using _Str_view = basic_string_view<_CharT>;
1103  using _UChar = make_unsigned_t<_CharT>;
1104  using _Esc = _Escapes<_CharT>;
1105 
1106  static constexpr char32_t __replace = U'\uFFFD';
1107  static constexpr _Str_view __replace_rep = []
1108  {
1109  // N.B. "\uFFFD" is ill-formed if encoding is not unicode.
1110  if constexpr (is_same_v<char, _CharT>)
1111  return "\xEF\xBF\xBD";
1112  else
1113  return L"\xFFFD";
1114  }();
1115 
1116  __unicode::_Utf_view<char32_t, _Str_view> __v(std::move(__str));
1117  auto __first = __v.begin();
1118  auto const __last = __v.end();
1119 
1120  bool __prev_esc = true;
1121  while (__first != __last)
1122  {
1123  bool __esc_ascii = false;
1124  bool __esc_unicode = false;
1125  bool __esc_replace = false;
1126  auto __should_escape = [&](auto const& __it)
1127  {
1128  if (*__it <= 0x7f)
1129  return __esc_ascii
1130  = __format::__should_escape_ascii(*__it.base(), __term);
1131  if (__format::__should_escape_unicode(*__it, __prev_esc))
1132  return __esc_unicode = true;
1133  if (*__it == __replace)
1134  {
1135  _Str_view __units(__it.base(), __it._M_units());
1136  return __esc_replace = (__units != __replace_rep);
1137  }
1138  return false;
1139  };
1140 
1141  auto __print = __first;
1142  while (__print != __last && !__should_escape(__print))
1143  {
1144  __prev_esc = false;
1145  ++__print;
1146  }
1147 
1148  if (__print != __first)
1149  __out = __format::__write(__out, _Str_view(__first.base(), __print.base()));
1150 
1151  if (__print == __last)
1152  return __out;
1153 
1154  __first = __print;
1155  if (__esc_ascii)
1156  __out = __format::__write_escaped_char(__out, *__first.base());
1157  else if (__esc_unicode)
1158  __out = __format::__write_escape_seq(__out, *__first, _Esc::_S_u());
1159  else // __esc_replace
1160  for (_CharT __c : _Str_view(__first.base(), __first._M_units()))
1161  __out = __format::__write_escape_seq(__out,
1162  static_cast<_UChar>(__c),
1163  _Esc::_S_x());
1164  __prev_esc = true;
1165  ++__first;
1166 
1167  }
1168  return __out;
1169  }
1170 
1171  template<typename _CharT, typename _Out>
1172  _Out
1173  __write_escaped(_Out __out, basic_string_view<_CharT> __str, _Term_char __term)
1174  {
1175  *__out = _Escapes<_CharT>::_S_term(__term);
1176  ++__out;
1177 
1178  if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
1179  __out = __format::__write_escaped_unicode(__out, __str, __term);
1180  else if constexpr (is_same_v<char, _CharT>
1181  && __unicode::__literal_encoding_is_extended_ascii())
1182  __out = __format::__write_escaped_ascii(__out, __str, __term);
1183  else
1184  // TODO Handle non-ascii extended encoding
1185  __out = __format::__write_escaped_ascii(__out, __str, __term);
1186 
1187  *__out = _Escapes<_CharT>::_S_term(__term);
1188  return ++__out;
1189  }
1190 
1191  // A lightweight optional<locale>.
1192  struct _Optional_locale
1193  {
1194  [[__gnu__::__always_inline__]]
1195  _Optional_locale() : _M_dummy(), _M_hasval(false) { }
1196 
1197  _Optional_locale(const locale& __loc) noexcept
1198  : _M_loc(__loc), _M_hasval(true)
1199  { }
1200 
1201  _Optional_locale(const _Optional_locale& __l) noexcept
1202  : _M_dummy(), _M_hasval(__l._M_hasval)
1203  {
1204  if (_M_hasval)
1205  std::construct_at(&_M_loc, __l._M_loc);
1206  }
1207 
1208  _Optional_locale&
1209  operator=(const _Optional_locale& __l) noexcept
1210  {
1211  if (_M_hasval)
1212  {
1213  if (__l._M_hasval)
1214  _M_loc = __l._M_loc;
1215  else
1216  {
1217  _M_loc.~locale();
1218  _M_hasval = false;
1219  }
1220  }
1221  else if (__l._M_hasval)
1222  {
1223  std::construct_at(&_M_loc, __l._M_loc);
1224  _M_hasval = true;
1225  }
1226  return *this;
1227  }
1228 
1229  ~_Optional_locale() { if (_M_hasval) _M_loc.~locale(); }
1230 
1231  _Optional_locale&
1232  operator=(locale&& __loc) noexcept
1233  {
1234  if (_M_hasval)
1235  _M_loc = std::move(__loc);
1236  else
1237  {
1238  std::construct_at(&_M_loc, std::move(__loc));
1239  _M_hasval = true;
1240  }
1241  return *this;
1242  }
1243 
1244  const locale&
1245  value() noexcept
1246  {
1247  if (!_M_hasval)
1248  {
1249  std::construct_at(&_M_loc);
1250  _M_hasval = true;
1251  }
1252  return _M_loc;
1253  }
1254 
1255  bool has_value() const noexcept { return _M_hasval; }
1256 
1257  union {
1258  char _M_dummy = '\0';
1259  std::locale _M_loc;
1260  };
1261  bool _M_hasval = false;
1262  };
1263 
1264  template<__char _CharT>
1265  struct __formatter_str
1266  {
1267  __formatter_str() = default;
1268 
1269  constexpr
1270  __formatter_str(_Spec<_CharT> __spec) noexcept
1271  : _M_spec(__spec)
1272  { }
1273 
1274  constexpr typename basic_format_parse_context<_CharT>::iterator
1275  parse(basic_format_parse_context<_CharT>& __pc)
1276  {
1277  auto __first = __pc.begin();
1278  const auto __last = __pc.end();
1279  _Spec<_CharT> __spec{};
1280 
1281  auto __finalize = [this, &__spec] {
1282  _M_spec = __spec;
1283  };
1284 
1285  auto __finished = [&] {
1286  if (__first == __last || *__first == '}')
1287  {
1288  __finalize();
1289  return true;
1290  }
1291  return false;
1292  };
1293 
1294  if (__finished())
1295  return __first;
1296 
1297  __first = __spec._M_parse_fill_and_align(__first, __last);
1298  if (__finished())
1299  return __first;
1300 
1301  __first = __spec._M_parse_width(__first, __last, __pc);
1302  if (__finished())
1303  return __first;
1304 
1305  __first = __spec._M_parse_precision(__first, __last, __pc);
1306  if (__finished())
1307  return __first;
1308 
1309  if (*__first == 's')
1310  ++__first;
1311 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
1312  else if (*__first == '?')
1313  {
1314  __spec._M_type = _Pres_esc;
1315  ++__first;
1316  }
1317 #endif
1318 
1319  if (__finished())
1320  return __first;
1321 
1322  __format::__failed_to_parse_format_spec();
1323  }
1324 
1325  template<typename _Out>
1326  _Out
1327  format(basic_string_view<_CharT> __s,
1328  basic_format_context<_Out, _CharT>& __fc) const
1329  {
1330  constexpr auto __term = __format::_Term_char::_Tc_quote;
1331  const auto __write_direct = [&]
1332  {
1333  if (_M_spec._M_type == _Pres_esc)
1334  return __format::__write_escaped(__fc.out(), __s, __term);
1335  else
1336  return __format::__write(__fc.out(), __s);
1337  };
1338 
1339  if (_M_spec._M_width_kind == _WP_none
1340  && _M_spec._M_prec_kind == _WP_none)
1341  return __write_direct();
1342 
1343  const size_t __prec =
1344  _M_spec._M_prec_kind != _WP_none
1345  ? _M_spec._M_get_precision(__fc)
1346  : basic_string_view<_CharT>::npos;
1347 
1348  const size_t __estimated_width = _S_trunc(__s, __prec);
1349  // N.B. Escaping only increases width
1350  if (_M_spec._M_get_width(__fc) <= __estimated_width
1351  && _M_spec._M_prec_kind == _WP_none)
1352  return __write_direct();
1353 
1354  if (_M_spec._M_type != _Pres_esc)
1355  return __format::__write_padded_as_spec(__s, __estimated_width,
1356  __fc, _M_spec);
1357 
1358  __format::_Str_sink<_CharT> __sink;
1359  __format::__write_escaped(__sink.out(), __s, __term);
1360  basic_string_view<_CharT> __escaped(__sink.view().data(),
1361  __sink.view().size());
1362  const size_t __escaped_width = _S_trunc(__escaped, __prec);
1363  // N.B. [tab:format.type.string] defines '?' as
1364  // Copies the escaped string ([format.string.escaped]) to the output,
1365  // so precision seem to appy to escaped string.
1366  return __format::__write_padded_as_spec(__escaped, __escaped_width,
1367  __fc, _M_spec);
1368  }
1369 
1370 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
1371  template<ranges::input_range _Rg, typename _Out>
1372  requires same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _CharT>
1373  typename basic_format_context<_Out, _CharT>::iterator
1374  _M_format_range(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
1375  {
1376  using _String = basic_string<_CharT>;
1377  using _String_view = basic_string_view<_CharT>;
1378  if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
1379  {
1380  const size_t __n(ranges::distance(__rg));
1381  if constexpr (ranges::contiguous_range<_Rg>)
1382  return format(_String_view(ranges::data(__rg), __n), __fc);
1383  else if (__n <= __format::__stackbuf_size<_CharT>)
1384  {
1385  _CharT __buf[__format::__stackbuf_size<_CharT>];
1386  ranges::copy(__rg, __buf);
1387  return format(_String_view(__buf, __n), __fc);
1388  }
1389  else if constexpr (ranges::sized_range<_Rg>)
1390  return format(_String(from_range, __rg), __fc);
1391  else if constexpr (ranges::random_access_range<_Rg>)
1392  {
1393  ranges::iterator_t<_Rg> __first = ranges::begin(__rg);
1394  ranges::subrange __sub(__first, __first + __n);
1395  return format(_String(from_range, __sub), __fc);
1396  }
1397  else
1398  {
1399  // N.B. preserve the computed size
1400  ranges::subrange __sub(__rg, __n);
1401  return format(_String(from_range, __sub), __fc);
1402  }
1403  }
1404  else
1405  return format(_String(from_range, __rg), __fc);
1406  }
1407 
1408  constexpr void
1409  set_debug_format() noexcept
1410  { _M_spec._M_type = _Pres_esc; }
1411 #endif
1412 
1413  private:
1414  static size_t
1415  _S_trunc(basic_string_view<_CharT>& __s, size_t __prec)
1416  {
1417  if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
1418  {
1419  if (__prec != basic_string_view<_CharT>::npos)
1420  return __unicode::__truncate(__s, __prec);
1421  else
1422  return __unicode::__field_width(__s);
1423  }
1424  else
1425  {
1426  __s = __s.substr(0, __prec);
1427  return __s.size();
1428  }
1429  }
1430 
1431  _Spec<_CharT> _M_spec{};
1432  };
1433 
1434  template<__char _CharT>
1435  struct __formatter_int
1436  {
1437  // If no presentation type is specified, meaning of "none" depends
1438  // whether we are formatting an integer or a char or a bool.
1439  static constexpr _Pres_type _AsInteger = _Pres_d;
1440  static constexpr _Pres_type _AsBool = _Pres_s;
1441  static constexpr _Pres_type _AsChar = _Pres_c;
1442 
1443  constexpr typename basic_format_parse_context<_CharT>::iterator
1444  _M_do_parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type)
1445  {
1446  _Spec<_CharT> __spec{};
1447  __spec._M_type = __type;
1448 
1449  const auto __last = __pc.end();
1450  auto __first = __pc.begin();
1451 
1452  auto __finalize = [this, &__spec] {
1453  _M_spec = __spec;
1454  };
1455 
1456  auto __finished = [&] {
1457  if (__first == __last || *__first == '}')
1458  {
1459  __finalize();
1460  return true;
1461  }
1462  return false;
1463  };
1464 
1465  if (__finished())
1466  return __first;
1467 
1468  __first = __spec._M_parse_fill_and_align(__first, __last);
1469  if (__finished())
1470  return __first;
1471 
1472  __first = __spec._M_parse_sign(__first, __last);
1473  if (__finished())
1474  return __first;
1475 
1476  __first = __spec._M_parse_alternate_form(__first, __last);
1477  if (__finished())
1478  return __first;
1479 
1480  __first = __spec._M_parse_zero_fill(__first, __last);
1481  if (__finished())
1482  return __first;
1483 
1484  __first = __spec._M_parse_width(__first, __last, __pc);
1485  if (__finished())
1486  return __first;
1487 
1488  __first = __spec._M_parse_locale(__first, __last);
1489  if (__finished())
1490  return __first;
1491 
1492  switch (*__first)
1493  {
1494  case 'b':
1495  __spec._M_type = _Pres_b;
1496  ++__first;
1497  break;
1498  case 'B':
1499  __spec._M_type = _Pres_B;
1500  ++__first;
1501  break;
1502  case 'c':
1503  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1504  // 3586. format should not print bool with 'c'
1505  if (__type != _AsBool)
1506  {
1507  __spec._M_type = _Pres_c;
1508  ++__first;
1509  }
1510  break;
1511  case 'd':
1512  __spec._M_type = _Pres_d;
1513  ++__first;
1514  break;
1515  case 'o':
1516  __spec._M_type = _Pres_o;
1517  ++__first;
1518  break;
1519  case 'x':
1520  __spec._M_type = _Pres_x;
1521  ++__first;
1522  break;
1523  case 'X':
1524  __spec._M_type = _Pres_X;
1525  ++__first;
1526  break;
1527  case 's':
1528  if (__type == _AsBool)
1529  {
1530  __spec._M_type = _Pres_s; // same value (and meaning) as "none"
1531  ++__first;
1532  }
1533  break;
1534 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
1535  case '?':
1536  if (__type == _AsChar)
1537  {
1538  __spec._M_type = _Pres_esc;
1539  ++__first;
1540  }
1541 #endif
1542  break;
1543  }
1544 
1545  if (__finished())
1546  return __first;
1547 
1548  __format::__failed_to_parse_format_spec();
1549  }
1550 
1551  template<typename _Tp>
1552  constexpr typename basic_format_parse_context<_CharT>::iterator
1553  _M_parse(basic_format_parse_context<_CharT>& __pc)
1554  {
1555  if constexpr (is_same_v<_Tp, bool>)
1556  {
1557  auto __end = _M_do_parse(__pc, _AsBool);
1558  if (_M_spec._M_type == _Pres_s)
1559  if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill)
1560  __throw_format_error("format error: format-spec contains "
1561  "invalid formatting options for "
1562  "'bool'");
1563  return __end;
1564  }
1565  else if constexpr (__char<_Tp>)
1566  {
1567  auto __end = _M_do_parse(__pc, _AsChar);
1568  if (_M_spec._M_type == _Pres_c || _M_spec._M_type == _Pres_esc)
1569  if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill
1570  /* XXX should be invalid? || _M_spec._M_localized */)
1571  __throw_format_error("format error: format-spec contains "
1572  "invalid formatting options for "
1573  "'charT'");
1574  return __end;
1575  }
1576  else
1577  return _M_do_parse(__pc, _AsInteger);
1578  }
1579 
1580  template<typename _Int, typename _Out>
1581  typename basic_format_context<_Out, _CharT>::iterator
1582  format(_Int __i, basic_format_context<_Out, _CharT>& __fc) const
1583  {
1584  if (_M_spec._M_type == _Pres_c)
1585  return _M_format_character(_S_to_character(__i), __fc);
1586 
1587  char __buf[sizeof(_Int) * __CHAR_BIT__ + 3];
1588  to_chars_result __res{};
1589 
1590  string_view __base_prefix;
1591  make_unsigned_t<_Int> __u;
1592  if (__i < 0)
1593  __u = -static_cast<make_unsigned_t<_Int>>(__i);
1594  else
1595  __u = __i;
1596 
1597  char* __start = __buf + 3;
1598  char* const __end = __buf + sizeof(__buf);
1599  char* const __start_digits = __start;
1600 
1601  switch (_M_spec._M_type)
1602  {
1603  case _Pres_b:
1604  case _Pres_B:
1605  __base_prefix = _M_spec._M_type == _Pres_b ? "0b" : "0B";
1606  __res = to_chars(__start, __end, __u, 2);
1607  break;
1608 #if 0
1609  case _Pres_c:
1610  return _M_format_character(_S_to_character(__i), __fc);
1611 #endif
1612  case _Pres_none:
1613  // Should not reach here with _Pres_none for bool or charT, so:
1614  [[fallthrough]];
1615  case _Pres_d:
1616  __res = to_chars(__start, __end, __u, 10);
1617  break;
1618  case _Pres_o:
1619  if (__i != 0)
1620  __base_prefix = "0";
1621  __res = to_chars(__start, __end, __u, 8);
1622  break;
1623  case _Pres_x:
1624  case _Pres_X:
1625  __base_prefix = _M_spec._M_type == _Pres_x ? "0x" : "0X";
1626  __res = to_chars(__start, __end, __u, 16);
1627  if (_M_spec._M_type == _Pres_X)
1628  for (auto __p = __start; __p != __res.ptr; ++__p)
1629 #if __has_builtin(__builtin_toupper)
1630  *__p = __builtin_toupper(*__p);
1631 #else
1632  *__p = std::toupper(*__p);
1633 #endif
1634  break;
1635  default:
1636  __builtin_unreachable();
1637  }
1638 
1639  if (_M_spec._M_alt && __base_prefix.size())
1640  {
1641  __start -= __base_prefix.size();
1642  __builtin_memcpy(__start, __base_prefix.data(),
1643  __base_prefix.size());
1644  }
1645  __start = __format::__put_sign(__i, _M_spec._M_sign, __start - 1);
1646 
1647  return _M_format_int(string_view(__start, __res.ptr - __start),
1648  __start_digits - __start, __fc);
1649  }
1650 
1651  template<typename _Out>
1652  typename basic_format_context<_Out, _CharT>::iterator
1653  format(bool __i, basic_format_context<_Out, _CharT>& __fc) const
1654  {
1655  if (_M_spec._M_type == _Pres_c)
1656  return _M_format_character(static_cast<unsigned char>(__i), __fc);
1657  if (_M_spec._M_type != _Pres_s)
1658  return format(static_cast<unsigned char>(__i), __fc);
1659 
1660  basic_string<_CharT> __s;
1661  size_t __est_width;
1662  if (_M_spec._M_localized) [[unlikely]]
1663  {
1664  auto& __np = std::use_facet<numpunct<_CharT>>(__fc.locale());
1665  __s = __i ? __np.truename() : __np.falsename();
1666  __est_width = __s.size(); // TODO Unicode-aware estimate
1667  }
1668  else
1669  {
1670  if constexpr (is_same_v<char, _CharT>)
1671  __s = __i ? "true" : "false";
1672  else
1673  __s = __i ? L"true" : L"false";
1674  __est_width = __s.size();
1675  }
1676 
1677  return __format::__write_padded_as_spec(__s, __est_width, __fc,
1678  _M_spec);
1679  }
1680 
1681  [[__gnu__::__always_inline__]]
1682  static size_t
1683  _S_character_width(_CharT __c)
1684  {
1685  // N.B. single byte cannot encode charcter of width greater than 1
1686  if constexpr (sizeof(_CharT) > 1u &&
1687  __unicode::__literal_encoding_is_unicode<_CharT>())
1688  return __unicode::__field_width(__c);
1689  else
1690  return 1u;
1691  }
1692 
1693  template<typename _Out>
1694  typename basic_format_context<_Out, _CharT>::iterator
1695  _M_format_character(_CharT __c,
1696  basic_format_context<_Out, _CharT>& __fc) const
1697  {
1698  return __format::__write_padded_as_spec({&__c, 1u},
1699  _S_character_width(__c),
1700  __fc, _M_spec);
1701  }
1702 
1703  template<typename _Out>
1704  typename basic_format_context<_Out, _CharT>::iterator
1705  _M_format_character_escaped(_CharT __c,
1706  basic_format_context<_Out, _CharT>& __fc) const
1707  {
1708  using _Esc = _Escapes<_CharT>;
1709  constexpr auto __term = __format::_Term_char::_Tc_apos;
1710  const basic_string_view<_CharT> __in(&__c, 1u);
1711  if (_M_spec._M_get_width(__fc) <= 3u)
1712  return __format::__write_escaped(__fc.out(), __in, __term);
1713 
1714  _CharT __buf[12];
1715  __format::_Fixedbuf_sink<_CharT> __sink(__buf);
1716  __format::__write_escaped(__sink.out(), __in, __term);
1717 
1718  const basic_string_view<_CharT> __escaped = __sink.view();
1719  size_t __estimated_width;
1720  if (__escaped[1] == _Esc::_S_bslash()[0]) // escape sequence
1721  __estimated_width = __escaped.size();
1722  else
1723  __estimated_width = 2 + _S_character_width(__c);
1724  return __format::__write_padded_as_spec(__escaped,
1725  __estimated_width,
1726  __fc, _M_spec);
1727  }
1728 
1729  template<typename _Int>
1730  static _CharT
1731  _S_to_character(_Int __i)
1732  {
1733  using _Traits = __gnu_cxx::__int_traits<_CharT>;
1734  if constexpr (is_signed_v<_Int> == is_signed_v<_CharT>)
1735  {
1736  if (_Traits::__min <= __i && __i <= _Traits::__max)
1737  return static_cast<_CharT>(__i);
1738  }
1739  else if constexpr (is_signed_v<_Int>)
1740  {
1741  if (__i >= 0 && make_unsigned_t<_Int>(__i) <= _Traits::__max)
1742  return static_cast<_CharT>(__i);
1743  }
1744  else if (__i <= make_unsigned_t<_CharT>(_Traits::__max))
1745  return static_cast<_CharT>(__i);
1746  __throw_format_error("format error: integer not representable as "
1747  "character");
1748  }
1749 
1750  template<typename _Out>
1751  typename basic_format_context<_Out, _CharT>::iterator
1752  _M_format_int(string_view __narrow_str, size_t __prefix_len,
1753  basic_format_context<_Out, _CharT>& __fc) const
1754  {
1755  size_t __width = _M_spec._M_get_width(__fc);
1756 
1757  basic_string_view<_CharT> __str;
1758  if constexpr (is_same_v<char, _CharT>)
1759  __str = __narrow_str;
1760 #ifdef _GLIBCXX_USE_WCHAR_T
1761  else
1762  {
1763  size_t __n = __narrow_str.size();
1764  auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
1765  std::__to_wstring_numeric(__narrow_str.data(), __n, __p);
1766  __str = {__p, __n};
1767  }
1768 #endif
1769 
1770  if (_M_spec._M_localized)
1771  {
1772  const auto& __l = __fc.locale();
1773  if (__l.name() != "C")
1774  {
1775  auto& __np = use_facet<numpunct<_CharT>>(__l);
1776  string __grp = __np.grouping();
1777  if (!__grp.empty())
1778  {
1779  size_t __n = __str.size() - __prefix_len;
1780  auto __p = (_CharT*)__builtin_alloca(2 * __n
1781  * sizeof(_CharT)
1782  + __prefix_len);
1783  auto __s = __str.data();
1784  char_traits<_CharT>::copy(__p, __s, __prefix_len);
1785  __s += __prefix_len;
1786  auto __end = std::__add_grouping(__p + __prefix_len,
1787  __np.thousands_sep(),
1788  __grp.data(),
1789  __grp.size(),
1790  __s, __s + __n);
1791  __str = {__p, size_t(__end - __p)};
1792  }
1793  }
1794  }
1795 
1796  if (__width <= __str.size())
1797  return __format::__write(__fc.out(), __str);
1798 
1799  char32_t __fill_char = _M_spec._M_fill;
1800  _Align __align = _M_spec._M_align;
1801 
1802  size_t __nfill = __width - __str.size();
1803  auto __out = __fc.out();
1804  if (__align == _Align_default)
1805  {
1806  __align = _Align_right;
1807  if (_M_spec._M_zero_fill)
1808  {
1809  __fill_char = _CharT('0');
1810  // Write sign and base prefix before zero filling.
1811  if (__prefix_len != 0)
1812  {
1813  __out = __format::__write(std::move(__out),
1814  __str.substr(0, __prefix_len));
1815  __str.remove_prefix(__prefix_len);
1816  }
1817  }
1818  else
1819  __fill_char = _CharT(' ');
1820  }
1821  return __format::__write_padded(std::move(__out), __str,
1822  __align, __nfill, __fill_char);
1823  }
1824 
1825 #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__
1826  template<typename _Tp>
1827  using make_unsigned_t
1828  = typename __conditional_t<(sizeof(_Tp) <= sizeof(long long)),
1829  std::make_unsigned<_Tp>,
1830  type_identity<unsigned __int128>>::type;
1831 
1832  // std::to_chars is not overloaded for int128 in strict mode.
1833  template<typename _Int>
1834  static to_chars_result
1835  to_chars(char* __first, char* __last, _Int __value, int __base)
1836  { return std::__to_chars_i<_Int>(__first, __last, __value, __base); }
1837 #endif
1838 
1839  _Spec<_CharT> _M_spec{};
1840  };
1841 
1842  // Decide how 128-bit floating-point types should be formatted (or not).
1843  // When supported, the typedef __format::__float128_t is the type that
1844  // format arguments should be converted to for storage in basic_format_arg.
1845  // Define the macro _GLIBCXX_FORMAT_F128 to say they're supported.
1846  // _GLIBCXX_FORMAT_F128=1 means __float128, _Float128 etc. will be formatted
1847  // by converting them to long double (or __ieee128 for powerpc64le).
1848  // _GLIBCXX_FORMAT_F128=2 means basic_format_arg needs to enable explicit
1849  // support for _Float128, rather than formatting it as another type.
1850 #undef _GLIBCXX_FORMAT_F128
1851 
1852 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
1853 
1854  // Format 128-bit floating-point types using __ieee128.
1855  using __float128_t = __ieee128;
1856 # define _GLIBCXX_FORMAT_F128 1
1857 
1858 #ifdef __LONG_DOUBLE_IEEE128__
1859  // These overloads exist in the library, but are not declared.
1860  // Make them available as std::__format::to_chars.
1861  to_chars_result
1862  to_chars(char*, char*, __ibm128) noexcept
1863  __asm("_ZSt8to_charsPcS_e");
1864 
1865  to_chars_result
1866  to_chars(char*, char*, __ibm128, chars_format) noexcept
1867  __asm("_ZSt8to_charsPcS_eSt12chars_format");
1868 
1869  to_chars_result
1870  to_chars(char*, char*, __ibm128, chars_format, int) noexcept
1871  __asm("_ZSt8to_charsPcS_eSt12chars_formati");
1872 #elif __cplusplus == 202002L
1873  to_chars_result
1874  to_chars(char*, char*, __ieee128) noexcept
1875  __asm("_ZSt8to_charsPcS_u9__ieee128");
1876 
1877  to_chars_result
1878  to_chars(char*, char*, __ieee128, chars_format) noexcept
1879  __asm("_ZSt8to_charsPcS_u9__ieee128St12chars_format");
1880 
1881  to_chars_result
1882  to_chars(char*, char*, __ieee128, chars_format, int) noexcept
1883  __asm("_ZSt8to_charsPcS_u9__ieee128St12chars_formati");
1884 #endif
1885 
1886 #elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128
1887 
1888  // Format 128-bit floating-point types using long double.
1889  using __float128_t = long double;
1890 # define _GLIBCXX_FORMAT_F128 1
1891 
1892 #elif __FLT128_DIG__ && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
1893 
1894  // Format 128-bit floating-point types using _Float128.
1895  using __float128_t = _Float128;
1896 # define _GLIBCXX_FORMAT_F128 2
1897 
1898 # if __cplusplus == 202002L
1899  // These overloads exist in the library, but are not declared for C++20.
1900  // Make them available as std::__format::to_chars.
1901  to_chars_result
1902  to_chars(char*, char*, _Float128) noexcept
1903 # if _GLIBCXX_INLINE_VERSION
1904  __asm("_ZNSt3__88to_charsEPcS0_DF128_");
1905 # else
1906  __asm("_ZSt8to_charsPcS_DF128_");
1907 # endif
1908 
1909  to_chars_result
1910  to_chars(char*, char*, _Float128, chars_format) noexcept
1911 # if _GLIBCXX_INLINE_VERSION
1912  __asm("_ZNSt3__88to_charsEPcS0_DF128_NS_12chars_formatE");
1913 # else
1914  __asm("_ZSt8to_charsPcS_DF128_St12chars_format");
1915 # endif
1916 
1917  to_chars_result
1918  to_chars(char*, char*, _Float128, chars_format, int) noexcept
1919 # if _GLIBCXX_INLINE_VERSION
1920  __asm("_ZNSt3__88to_charsEPcS0_DF128_NS_12chars_formatEi");
1921 # else
1922  __asm("_ZSt8to_charsPcS_DF128_St12chars_formati");
1923 # endif
1924 # endif
1925 #endif
1926 
1927  using std::to_chars;
1928 
1929  // We can format a floating-point type iff it is usable with to_chars.
1930  template<typename _Tp>
1931  concept __formattable_float
1932  = is_same_v<remove_cv_t<_Tp>, _Tp> && requires (_Tp __t, char* __p)
1933  { __format::to_chars(__p, __p, __t, chars_format::scientific, 6); };
1934 
1935  template<__char _CharT>
1936  struct __formatter_fp
1937  {
1938  constexpr typename basic_format_parse_context<_CharT>::iterator
1939  parse(basic_format_parse_context<_CharT>& __pc)
1940  {
1941  _Spec<_CharT> __spec{};
1942  const auto __last = __pc.end();
1943  auto __first = __pc.begin();
1944 
1945  auto __finalize = [this, &__spec] {
1946  _M_spec = __spec;
1947  };
1948 
1949  auto __finished = [&] {
1950  if (__first == __last || *__first == '}')
1951  {
1952  __finalize();
1953  return true;
1954  }
1955  return false;
1956  };
1957 
1958  if (__finished())
1959  return __first;
1960 
1961  __first = __spec._M_parse_fill_and_align(__first, __last);
1962  if (__finished())
1963  return __first;
1964 
1965  __first = __spec._M_parse_sign(__first, __last);
1966  if (__finished())
1967  return __first;
1968 
1969  __first = __spec._M_parse_alternate_form(__first, __last);
1970  if (__finished())
1971  return __first;
1972 
1973  __first = __spec._M_parse_zero_fill(__first, __last);
1974  if (__finished())
1975  return __first;
1976 
1977  if (__first[0] != '.')
1978  {
1979  __first = __spec._M_parse_width(__first, __last, __pc);
1980  if (__finished())
1981  return __first;
1982  }
1983 
1984  __first = __spec._M_parse_precision(__first, __last, __pc);
1985  if (__finished())
1986  return __first;
1987 
1988  __first = __spec._M_parse_locale(__first, __last);
1989  if (__finished())
1990  return __first;
1991 
1992  switch (*__first)
1993  {
1994  case 'a':
1995  __spec._M_type = _Pres_a;
1996  ++__first;
1997  break;
1998  case 'A':
1999  __spec._M_type = _Pres_A;
2000  ++__first;
2001  break;
2002  case 'e':
2003  __spec._M_type = _Pres_e;
2004  ++__first;
2005  break;
2006  case 'E':
2007  __spec._M_type = _Pres_E;
2008  ++__first;
2009  break;
2010  case 'f':
2011  __spec._M_type = _Pres_f;
2012  ++__first;
2013  break;
2014  case 'F':
2015  __spec._M_type = _Pres_F;
2016  ++__first;
2017  break;
2018  case 'g':
2019  __spec._M_type = _Pres_g;
2020  ++__first;
2021  break;
2022  case 'G':
2023  __spec._M_type = _Pres_G;
2024  ++__first;
2025  break;
2026  }
2027 
2028  if (__finished())
2029  return __first;
2030 
2031  __format::__failed_to_parse_format_spec();
2032  }
2033 
2034  template<typename _Fp, typename _Out>
2035  typename basic_format_context<_Out, _CharT>::iterator
2036  format(_Fp __v, basic_format_context<_Out, _CharT>& __fc) const
2037  {
2038  std::string __dynbuf;
2039  char __buf[128];
2040  to_chars_result __res{};
2041 
2042  size_t __prec = 6;
2043  bool __use_prec = _M_spec._M_prec_kind != _WP_none;
2044  if (__use_prec)
2045  __prec = _M_spec._M_get_precision(__fc);
2046 
2047  char* __start = __buf + 1; // reserve space for sign
2048  char* __end = __buf + sizeof(__buf);
2049 
2050  chars_format __fmt{};
2051  bool __upper = false;
2052  bool __trailing_zeros = false;
2053  char __expc = 'e';
2054 
2055  switch (_M_spec._M_type)
2056  {
2057  case _Pres_A:
2058  __upper = true;
2059  __expc = 'P';
2060  [[fallthrough]];
2061  case _Pres_a:
2062  if (_M_spec._M_type != _Pres_A)
2063  __expc = 'p';
2064  __fmt = chars_format::hex;
2065  break;
2066  case _Pres_E:
2067  __upper = true;
2068  __expc = 'E';
2069  [[fallthrough]];
2070  case _Pres_e:
2071  __use_prec = true;
2072  __fmt = chars_format::scientific;
2073  break;
2074  case _Pres_F:
2075  __upper = true;
2076  [[fallthrough]];
2077  case _Pres_f:
2078  __use_prec = true;
2079  __fmt = chars_format::fixed;
2080  break;
2081  case _Pres_G:
2082  __upper = true;
2083  __expc = 'E';
2084  [[fallthrough]];
2085  case _Pres_g:
2086  __trailing_zeros = true;
2087  __use_prec = true;
2088  __fmt = chars_format::general;
2089  break;
2090  case _Pres_none:
2091  if (__use_prec)
2092  __fmt = chars_format::general;
2093  break;
2094  default:
2095  __builtin_unreachable();
2096  }
2097 
2098  // Write value into buffer using std::to_chars.
2099  auto __to_chars = [&](char* __b, char* __e) {
2100  if (__use_prec)
2101  return __format::to_chars(__b, __e, __v, __fmt, __prec);
2102  else if (__fmt != chars_format{})
2103  return __format::to_chars(__b, __e, __v, __fmt);
2104  else
2105  return __format::to_chars(__b, __e, __v);
2106  };
2107 
2108  // First try using stack buffer.
2109  __res = __to_chars(__start, __end);
2110 
2111  if (__builtin_expect(__res.ec == errc::value_too_large, 0))
2112  {
2113  // If the buffer is too small it's probably because of a large
2114  // precision, or a very large value in fixed format.
2115  size_t __guess = 8 + __prec;
2116  if (__fmt == chars_format::fixed) // +ddd.prec
2117  {
2118  if constexpr (is_same_v<_Fp, float> || is_same_v<_Fp, double>
2119  || is_same_v<_Fp, long double>)
2120  {
2121  // The number of digits to the left of the decimal point
2122  // is floor(log10(max(abs(__v),1)))+1
2123  int __exp{};
2124  if constexpr (is_same_v<_Fp, float>)
2125  __builtin_frexpf(__v, &__exp);
2126  else if constexpr (is_same_v<_Fp, double>)
2127  __builtin_frexp(__v, &__exp);
2128  else if constexpr (is_same_v<_Fp, long double>)
2129  __builtin_frexpl(__v, &__exp);
2130  if (__exp > 0)
2131  __guess += 1U + __exp * 4004U / 13301U; // log10(2) approx.
2132  }
2133  else
2134  __guess += numeric_limits<_Fp>::max_exponent10;
2135  }
2136  if (__guess <= sizeof(__buf)) [[unlikely]]
2137  __guess = sizeof(__buf) * 2;
2138  __dynbuf.reserve(__guess);
2139 
2140  do
2141  {
2142  // Mangling of this lambda, and thus resize_and_overwrite
2143  // instantiated with it, was fixed in ABI 18 (G++ 13). Since
2144  // <format> was new in G++ 13, and is experimental, that
2145  // isn't a problem.
2146  auto __overwrite = [&__to_chars, &__res] (char* __p, size_t __n)
2147  {
2148  __res = __to_chars(__p + 1, __p + __n - 1);
2149  return __res.ec == errc{} ? __res.ptr - __p : 0;
2150  };
2151 
2152  __dynbuf.__resize_and_overwrite(__dynbuf.capacity() * 2,
2153  __overwrite);
2154  __start = __dynbuf.data() + 1; // reserve space for sign
2155  __end = __dynbuf.data() + __dynbuf.size();
2156  }
2157  while (__builtin_expect(__res.ec == errc::value_too_large, 0));
2158  }
2159 
2160  // Use uppercase for 'A', 'E', and 'G' formats.
2161  if (__upper)
2162  {
2163  for (char* __p = __start; __p != __res.ptr; ++__p)
2164  *__p = std::toupper(*__p);
2165  }
2166 
2167  bool __have_sign = true;
2168  // Add sign for non-negative values.
2169  if (!__builtin_signbit(__v))
2170  {
2171  if (_M_spec._M_sign == _Sign_plus)
2172  *--__start = '+';
2173  else if (_M_spec._M_sign == _Sign_space)
2174  *--__start = ' ';
2175  else
2176  __have_sign = false;
2177  }
2178 
2179  string_view __narrow_str(__start, __res.ptr - __start);
2180 
2181  // Use alternate form. Ensure decimal point is always present,
2182  // and add trailing zeros (up to precision) for g and G forms.
2183  if (_M_spec._M_alt && __builtin_isfinite(__v))
2184  {
2185  string_view __s = __narrow_str;
2186  size_t __sigfigs; // Number of significant figures.
2187  size_t __z = 0; // Number of trailing zeros to add.
2188  size_t __p; // Position of the exponent character (if any).
2189  size_t __d = __s.find('.'); // Position of decimal point.
2190  if (__d != __s.npos) // Found decimal point.
2191  {
2192  __p = __s.find(__expc, __d + 1);
2193  if (__p == __s.npos)
2194  __p = __s.size();
2195 
2196  // If presentation type is g or G we might need to add zeros.
2197  if (__trailing_zeros)
2198  {
2199  // Find number of digits after first significant figure.
2200  if (__s[__have_sign] != '0')
2201  // A string like "D.D" or "-D.DDD"
2202  __sigfigs = __p - __have_sign - 1;
2203  else
2204  // A string like "0.D" or "-0.0DD".
2205  // Safe to assume there is a non-zero digit, because
2206  // otherwise there would be no decimal point.
2207  __sigfigs = __p - __s.find_first_not_of('0', __d + 1);
2208  }
2209  }
2210  else // No decimal point, we need to insert one.
2211  {
2212  __p = __s.find(__expc); // Find the exponent, if present.
2213  if (__p == __s.npos)
2214  __p = __s.size();
2215  __d = __p; // Position where '.' should be inserted.
2216  __sigfigs = __d - __have_sign;
2217  }
2218 
2219  if (__trailing_zeros && __prec != 0)
2220  {
2221  // For g and G presentation types std::to_chars produces
2222  // no more than prec significant figures. Insert this many
2223  // zeros so the result has exactly prec significant figures.
2224  __z = __prec - __sigfigs;
2225  }
2226 
2227  if (size_t __extras = int(__d == __p) + __z) // How many to add.
2228  {
2229  if (__dynbuf.empty() && __extras <= size_t(__end - __res.ptr))
2230  {
2231  // The stack buffer is large enough for the result.
2232  // Move exponent to make space for extra chars.
2233  __builtin_memmove(__start + __p + __extras,
2234  __start + __p,
2235  __s.size() - __p);
2236  if (__d == __p)
2237  __start[__p++] = '.';
2238  __builtin_memset(__start + __p, '0', __z);
2239  __narrow_str = {__s.data(), __s.size() + __extras};
2240  }
2241  else // Need to switch to the dynamic buffer.
2242  {
2243  __dynbuf.reserve(__s.size() + __extras);
2244  if (__dynbuf.empty())
2245  {
2246  __dynbuf = __s.substr(0, __p);
2247  if (__d == __p)
2248  __dynbuf += '.';
2249  if (__z)
2250  __dynbuf.append(__z, '0');
2251  __dynbuf.append(__s.substr(__p));
2252  }
2253  else
2254  {
2255  __dynbuf.insert(__p, __extras, '0');
2256  if (__d == __p)
2257  __dynbuf[__p] = '.';
2258  }
2259  __narrow_str = __dynbuf;
2260  }
2261  }
2262  }
2263 
2264  basic_string<_CharT> __wstr;
2265  basic_string_view<_CharT> __str;
2266  if constexpr (is_same_v<_CharT, char>)
2267  __str = __narrow_str;
2268 #ifdef _GLIBCXX_USE_WCHAR_T
2269  else
2270  {
2271  __wstr = std::__to_wstring_numeric(__narrow_str);
2272  __str = __wstr;
2273  }
2274 #endif
2275 
2276  if (_M_spec._M_localized && __builtin_isfinite(__v))
2277  {
2278  auto __s = _M_localize(__str, __expc, __fc.locale());
2279  if (!__s.empty())
2280  __str = __wstr = std::move(__s);
2281  }
2282 
2283  size_t __width = _M_spec._M_get_width(__fc);
2284 
2285  if (__width <= __str.size())
2286  return __format::__write(__fc.out(), __str);
2287 
2288  char32_t __fill_char = _M_spec._M_fill;
2289  _Align __align = _M_spec._M_align;
2290 
2291  size_t __nfill = __width - __str.size();
2292  auto __out = __fc.out();
2293  if (__align == _Align_default)
2294  {
2295  __align = _Align_right;
2296  if (_M_spec._M_zero_fill && __builtin_isfinite(__v))
2297  {
2298  __fill_char = _CharT('0');
2299  // Write sign before zero filling.
2300  if (!__format::__is_xdigit(__narrow_str[0]))
2301  {
2302  *__out++ = __str[0];
2303  __str.remove_prefix(1);
2304  }
2305  }
2306  else
2307  __fill_char = _CharT(' ');
2308  }
2309  return __format::__write_padded(std::move(__out), __str,
2310  __align, __nfill, __fill_char);
2311  }
2312 
2313  // Locale-specific format.
2314  basic_string<_CharT>
2315  _M_localize(basic_string_view<_CharT> __str, char __expc,
2316  const locale& __loc) const
2317  {
2318  basic_string<_CharT> __lstr;
2319 
2320  if (__loc == locale::classic())
2321  return __lstr; // Nothing to do.
2322 
2323  const auto& __np = use_facet<numpunct<_CharT>>(__loc);
2324  const _CharT __point = __np.decimal_point();
2325  const string __grp = __np.grouping();
2326 
2327  _CharT __dot, __exp;
2328  if constexpr (is_same_v<_CharT, char>)
2329  {
2330  __dot = '.';
2331  __exp = __expc;
2332  }
2333  else
2334  {
2335  __dot = L'.';
2336  switch (__expc)
2337  {
2338  case 'e':
2339  __exp = L'e';
2340  break;
2341  case 'E':
2342  __exp = L'E';
2343  break;
2344  case 'p':
2345  __exp = L'p';
2346  break;
2347  case 'P':
2348  __exp = L'P';
2349  break;
2350  default:
2351  __builtin_unreachable();
2352  }
2353  }
2354 
2355  if (__grp.empty() && __point == __dot)
2356  return __lstr; // Locale uses '.' and no grouping.
2357 
2358  size_t __d = __str.find(__dot); // Index of radix character (if any).
2359  size_t __e = min(__d, __str.find(__exp)); // First of radix or exponent
2360  if (__e == __str.npos)
2361  __e = __str.size();
2362  const size_t __r = __str.size() - __e; // Length of remainder.
2363  auto __overwrite = [&](_CharT* __p, size_t) {
2364  // Apply grouping to the digits before the radix or exponent.
2365  int __off = 0;
2366  if (auto __c = __str.front(); __c == '-' || __c == '+' || __c == ' ')
2367  {
2368  *__p = __c;
2369  __off = 1;
2370  }
2371  auto __end = std::__add_grouping(__p + __off, __np.thousands_sep(),
2372  __grp.data(), __grp.size(),
2373  __str.data() + __off,
2374  __str.data() + __e);
2375  if (__r) // If there's a fractional part or exponent
2376  {
2377  if (__d != __str.npos)
2378  {
2379  *__end = __point; // Add the locale's radix character.
2380  ++__end;
2381  ++__e;
2382  }
2383  const size_t __rlen = __str.size() - __e;
2384  // Append fractional digits and/or exponent:
2385  char_traits<_CharT>::copy(__end, __str.data() + __e, __rlen);
2386  __end += __rlen;
2387  }
2388  return (__end - __p);
2389  };
2390  __lstr.__resize_and_overwrite(__e * 2 + __r, __overwrite);
2391  return __lstr;
2392  }
2393 
2394  _Spec<_CharT> _M_spec{};
2395  };
2396 
2397 } // namespace __format
2398 /// @endcond
2399 
2400  /// Format a character.
2401  template<__format::__char _CharT>
2402  struct formatter<_CharT, _CharT>
2403  {
2404  formatter() = default;
2405 
2406  constexpr typename basic_format_parse_context<_CharT>::iterator
2407  parse(basic_format_parse_context<_CharT>& __pc)
2408  {
2409  return _M_f.template _M_parse<_CharT>(__pc);
2410  }
2411 
2412  template<typename _Out>
2413  typename basic_format_context<_Out, _CharT>::iterator
2414  format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const
2415  {
2416  if (_M_f._M_spec._M_type == __format::_Pres_none
2417  || _M_f._M_spec._M_type == __format::_Pres_c)
2418  return _M_f._M_format_character(__u, __fc);
2419  else if (_M_f._M_spec._M_type == __format::_Pres_esc)
2420  return _M_f._M_format_character_escaped(__u, __fc);
2421  else
2422  return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u), __fc);
2423  }
2424 
2425 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2426  constexpr void
2427  set_debug_format() noexcept
2428  { _M_f._M_spec._M_type = __format::_Pres_esc; }
2429 #endif
2430 
2431  private:
2432  __format::__formatter_int<_CharT> _M_f;
2433  };
2434 
2435 #ifdef _GLIBCXX_USE_WCHAR_T
2436  /// Format a char value for wide character output.
2437  template<>
2438  struct formatter<char, wchar_t>
2439  {
2440  formatter() = default;
2441 
2442  constexpr typename basic_format_parse_context<wchar_t>::iterator
2443  parse(basic_format_parse_context<wchar_t>& __pc)
2444  {
2445  return _M_f._M_parse<char>(__pc);
2446  }
2447 
2448  template<typename _Out>
2449  typename basic_format_context<_Out, wchar_t>::iterator
2450  format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
2451  {
2452  if (_M_f._M_spec._M_type == __format::_Pres_none
2453  || _M_f._M_spec._M_type == __format::_Pres_c)
2454  return _M_f._M_format_character(__u, __fc);
2455  else if (_M_f._M_spec._M_type == __format::_Pres_esc)
2456  return _M_f._M_format_character_escaped(__u, __fc);
2457  else
2458  return _M_f.format(static_cast<unsigned char>(__u), __fc);
2459  }
2460 
2461 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2462  constexpr void
2463  set_debug_format() noexcept
2464  { _M_f._M_spec._M_type = __format::_Pres_esc; }
2465 #endif
2466 
2467  private:
2468  __format::__formatter_int<wchar_t> _M_f;
2469  };
2470 #endif // USE_WCHAR_T
2471 
2472  /** Format a string.
2473  * @{
2474  */
2475  template<__format::__char _CharT>
2476  struct formatter<_CharT*, _CharT>
2477  {
2478  formatter() = default;
2479 
2480  [[__gnu__::__always_inline__]]
2481  constexpr typename basic_format_parse_context<_CharT>::iterator
2482  parse(basic_format_parse_context<_CharT>& __pc)
2483  { return _M_f.parse(__pc); }
2484 
2485  template<typename _Out>
2486  [[__gnu__::__nonnull__]]
2487  typename basic_format_context<_Out, _CharT>::iterator
2488  format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc) const
2489  { return _M_f.format(__u, __fc); }
2490 
2491 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2492  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2493 #endif
2494 
2495  private:
2496  __format::__formatter_str<_CharT> _M_f;
2497  };
2498 
2499  template<__format::__char _CharT>
2500  struct formatter<const _CharT*, _CharT>
2501  {
2502  formatter() = default;
2503 
2504  [[__gnu__::__always_inline__]]
2505  constexpr typename basic_format_parse_context<_CharT>::iterator
2506  parse(basic_format_parse_context<_CharT>& __pc)
2507  { return _M_f.parse(__pc); }
2508 
2509  template<typename _Out>
2510  [[__gnu__::__nonnull__]]
2511  typename basic_format_context<_Out, _CharT>::iterator
2512  format(const _CharT* __u,
2513  basic_format_context<_Out, _CharT>& __fc) const
2514  { return _M_f.format(__u, __fc); }
2515 
2516 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2517  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2518 #endif
2519 
2520  private:
2521  __format::__formatter_str<_CharT> _M_f;
2522  };
2523 
2524  template<__format::__char _CharT, size_t _Nm>
2525  struct formatter<_CharT[_Nm], _CharT>
2526  {
2527  formatter() = default;
2528 
2529  [[__gnu__::__always_inline__]]
2530  constexpr typename basic_format_parse_context<_CharT>::iterator
2531  parse(basic_format_parse_context<_CharT>& __pc)
2532  { return _M_f.parse(__pc); }
2533 
2534  template<typename _Out>
2535  typename basic_format_context<_Out, _CharT>::iterator
2536  format(const _CharT (&__u)[_Nm],
2537  basic_format_context<_Out, _CharT>& __fc) const
2538  { return _M_f.format({__u, _Nm}, __fc); }
2539 
2540 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2541  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2542 #endif
2543 
2544  private:
2545  __format::__formatter_str<_CharT> _M_f;
2546  };
2547 
2548  template<typename _Traits, typename _Alloc>
2549  struct formatter<basic_string<char, _Traits, _Alloc>, char>
2550  {
2551  formatter() = default;
2552 
2553  [[__gnu__::__always_inline__]]
2554  constexpr typename basic_format_parse_context<char>::iterator
2555  parse(basic_format_parse_context<char>& __pc)
2556  { return _M_f.parse(__pc); }
2557 
2558  template<typename _Out>
2559  typename basic_format_context<_Out, char>::iterator
2560  format(const basic_string<char, _Traits, _Alloc>& __u,
2561  basic_format_context<_Out, char>& __fc) const
2562  { return _M_f.format(__u, __fc); }
2563 
2564 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2565  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2566 #endif
2567 
2568  private:
2569  __format::__formatter_str<char> _M_f;
2570  };
2571 
2572 #ifdef _GLIBCXX_USE_WCHAR_T
2573  template<typename _Traits, typename _Alloc>
2574  struct formatter<basic_string<wchar_t, _Traits, _Alloc>, wchar_t>
2575  {
2576  formatter() = default;
2577 
2578  [[__gnu__::__always_inline__]]
2579  constexpr typename basic_format_parse_context<wchar_t>::iterator
2580  parse(basic_format_parse_context<wchar_t>& __pc)
2581  { return _M_f.parse(__pc); }
2582 
2583  template<typename _Out>
2584  typename basic_format_context<_Out, wchar_t>::iterator
2585  format(const basic_string<wchar_t, _Traits, _Alloc>& __u,
2586  basic_format_context<_Out, wchar_t>& __fc) const
2587  { return _M_f.format(__u, __fc); }
2588 
2589 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2590  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2591 #endif
2592 
2593  private:
2594  __format::__formatter_str<wchar_t> _M_f;
2595  };
2596 #endif // USE_WCHAR_T
2597 
2598  template<typename _Traits>
2599  struct formatter<basic_string_view<char, _Traits>, char>
2600  {
2601  formatter() = default;
2602 
2603  [[__gnu__::__always_inline__]]
2604  constexpr typename basic_format_parse_context<char>::iterator
2605  parse(basic_format_parse_context<char>& __pc)
2606  { return _M_f.parse(__pc); }
2607 
2608  template<typename _Out>
2609  typename basic_format_context<_Out, char>::iterator
2610  format(basic_string_view<char, _Traits> __u,
2611  basic_format_context<_Out, char>& __fc) const
2612  { return _M_f.format(__u, __fc); }
2613 
2614 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2615  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2616 #endif
2617 
2618  private:
2619  __format::__formatter_str<char> _M_f;
2620  };
2621 
2622 #ifdef _GLIBCXX_USE_WCHAR_T
2623  template<typename _Traits>
2624  struct formatter<basic_string_view<wchar_t, _Traits>, wchar_t>
2625  {
2626  formatter() = default;
2627 
2628  [[__gnu__::__always_inline__]]
2629  constexpr typename basic_format_parse_context<wchar_t>::iterator
2630  parse(basic_format_parse_context<wchar_t>& __pc)
2631  { return _M_f.parse(__pc); }
2632 
2633  template<typename _Out>
2634  typename basic_format_context<_Out, wchar_t>::iterator
2635  format(basic_string_view<wchar_t, _Traits> __u,
2636  basic_format_context<_Out, wchar_t>& __fc) const
2637  { return _M_f.format(__u, __fc); }
2638 
2639 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
2640  constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); }
2641 #endif
2642 
2643  private:
2644  __format::__formatter_str<wchar_t> _M_f;
2645  };
2646 #endif // USE_WCHAR_T
2647  /// @}
2648 
2649 /// @cond undocumented
2650 namespace __format
2651 {
2652  // each cv-unqualified arithmetic type ArithmeticT other than
2653  // char, wchar_t, char8_t, char16_t, or char32_t
2654  template<typename _Tp>
2655  constexpr bool __is_formattable_integer = __is_integer<_Tp>::__value;
2656 
2657 #if defined __SIZEOF_INT128__
2658  template<> inline constexpr bool __is_formattable_integer<__int128> = true;
2659  template<> inline constexpr bool __is_formattable_integer<unsigned __int128>
2660  = true;
2661 #endif
2662 
2663  template<> inline constexpr bool __is_formattable_integer<char> = false;
2664  template<> inline constexpr bool __is_formattable_integer<wchar_t> = false;
2665 #ifdef _GLIBCXX_USE_CHAR8_T
2666  template<> inline constexpr bool __is_formattable_integer<char8_t> = false;
2667 #endif
2668  template<> inline constexpr bool __is_formattable_integer<char16_t> = false;
2669  template<> inline constexpr bool __is_formattable_integer<char32_t> = false;
2670 }
2671 /// @endcond
2672 
2673  /// Format an integer.
2674  template<typename _Tp, __format::__char _CharT>
2675  requires __format::__is_formattable_integer<_Tp>
2676  struct formatter<_Tp, _CharT>
2677  {
2678  formatter() = default;
2679 
2680  [[__gnu__::__always_inline__]]
2681  constexpr typename basic_format_parse_context<_CharT>::iterator
2682  parse(basic_format_parse_context<_CharT>& __pc)
2683  {
2684  return _M_f.template _M_parse<_Tp>(__pc);
2685  }
2686 
2687  template<typename _Out>
2688  typename basic_format_context<_Out, _CharT>::iterator
2689  format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
2690  { return _M_f.format(__u, __fc); }
2691 
2692  private:
2693  __format::__formatter_int<_CharT> _M_f;
2694  };
2695 
2696 #if defined __glibcxx_to_chars
2697  /// Format a floating-point value.
2698  template<__format::__formattable_float _Tp, __format::__char _CharT>
2699  struct formatter<_Tp, _CharT>
2700  {
2701  formatter() = default;
2702 
2703  [[__gnu__::__always_inline__]]
2704  constexpr typename basic_format_parse_context<_CharT>::iterator
2705  parse(basic_format_parse_context<_CharT>& __pc)
2706  { return _M_f.parse(__pc); }
2707 
2708  template<typename _Out>
2709  typename basic_format_context<_Out, _CharT>::iterator
2710  format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
2711  { return _M_f.format(__u, __fc); }
2712 
2713  private:
2714  __format::__formatter_fp<_CharT> _M_f;
2715  };
2716 
2717 #if __LDBL_MANT_DIG__ == __DBL_MANT_DIG__
2718  // Reuse __formatter_fp<C>::format<double, Out> for long double.
2719  template<__format::__char _CharT>
2720  struct formatter<long double, _CharT>
2721  {
2722  formatter() = default;
2723 
2724  [[__gnu__::__always_inline__]]
2725  constexpr typename basic_format_parse_context<_CharT>::iterator
2726  parse(basic_format_parse_context<_CharT>& __pc)
2727  { return _M_f.parse(__pc); }
2728 
2729  template<typename _Out>
2730  typename basic_format_context<_Out, _CharT>::iterator
2731  format(long double __u, basic_format_context<_Out, _CharT>& __fc) const
2732  { return _M_f.format((double)__u, __fc); }
2733 
2734  private:
2735  __format::__formatter_fp<_CharT> _M_f;
2736  };
2737 #endif
2738 
2739 #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
2740  // Reuse __formatter_fp<C>::format<float, Out> for _Float16.
2741  template<__format::__char _CharT>
2742  struct formatter<_Float16, _CharT>
2743  {
2744  formatter() = default;
2745 
2746  [[__gnu__::__always_inline__]]
2747  constexpr typename basic_format_parse_context<_CharT>::iterator
2748  parse(basic_format_parse_context<_CharT>& __pc)
2749  { return _M_f.parse(__pc); }
2750 
2751  template<typename _Out>
2752  typename basic_format_context<_Out, _CharT>::iterator
2753  format(_Float16 __u, basic_format_context<_Out, _CharT>& __fc) const
2754  { return _M_f.format((float)__u, __fc); }
2755 
2756  private:
2757  __format::__formatter_fp<_CharT> _M_f;
2758  };
2759 #endif
2760 
2761 #if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
2762  // Reuse __formatter_fp<C>::format<float, Out> for _Float32.
2763  template<__format::__char _CharT>
2764  struct formatter<_Float32, _CharT>
2765  {
2766  formatter() = default;
2767 
2768  [[__gnu__::__always_inline__]]
2769  constexpr typename basic_format_parse_context<_CharT>::iterator
2770  parse(basic_format_parse_context<_CharT>& __pc)
2771  { return _M_f.parse(__pc); }
2772 
2773  template<typename _Out>
2774  typename basic_format_context<_Out, _CharT>::iterator
2775  format(_Float32 __u, basic_format_context<_Out, _CharT>& __fc) const
2776  { return _M_f.format((float)__u, __fc); }
2777 
2778  private:
2779  __format::__formatter_fp<_CharT> _M_f;
2780  };
2781 #endif
2782 
2783 #if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
2784  // Reuse __formatter_fp<C>::format<double, Out> for _Float64.
2785  template<__format::__char _CharT>
2786  struct formatter<_Float64, _CharT>
2787  {
2788  formatter() = default;
2789 
2790  [[__gnu__::__always_inline__]]
2791  constexpr typename basic_format_parse_context<_CharT>::iterator
2792  parse(basic_format_parse_context<_CharT>& __pc)
2793  { return _M_f.parse(__pc); }
2794 
2795  template<typename _Out>
2796  typename basic_format_context<_Out, _CharT>::iterator
2797  format(_Float64 __u, basic_format_context<_Out, _CharT>& __fc) const
2798  { return _M_f.format((double)__u, __fc); }
2799 
2800  private:
2801  __format::__formatter_fp<_CharT> _M_f;
2802  };
2803 #endif
2804 
2805 #if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128 == 1
2806  // Reuse __formatter_fp<C>::format<__float128_t, Out> for _Float128.
2807  template<__format::__char _CharT>
2808  struct formatter<_Float128, _CharT>
2809  {
2810  formatter() = default;
2811 
2812  [[__gnu__::__always_inline__]]
2813  constexpr typename basic_format_parse_context<_CharT>::iterator
2814  parse(basic_format_parse_context<_CharT>& __pc)
2815  { return _M_f.parse(__pc); }
2816 
2817  template<typename _Out>
2818  typename basic_format_context<_Out, _CharT>::iterator
2819  format(_Float128 __u, basic_format_context<_Out, _CharT>& __fc) const
2820  { return _M_f.format((__format::__float128_t)__u, __fc); }
2821 
2822  private:
2823  __format::__formatter_fp<_CharT> _M_f;
2824  };
2825 #endif
2826 
2827 #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
2828  // Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t.
2829  template<__format::__char _CharT>
2830  struct formatter<__gnu_cxx::__bfloat16_t, _CharT>
2831  {
2832  formatter() = default;
2833 
2834  [[__gnu__::__always_inline__]]
2835  constexpr typename basic_format_parse_context<_CharT>::iterator
2836  parse(basic_format_parse_context<_CharT>& __pc)
2837  { return _M_f.parse(__pc); }
2838 
2839  template<typename _Out>
2840  typename basic_format_context<_Out, _CharT>::iterator
2841  format(__gnu_cxx::__bfloat16_t __u,
2842  basic_format_context<_Out, _CharT>& __fc) const
2843  { return _M_f.format((float)__u, __fc); }
2844 
2845  private:
2846  __format::__formatter_fp<_CharT> _M_f;
2847  };
2848 #endif
2849 #endif // __cpp_lib_to_chars
2850 
2851  /** Format a pointer.
2852  * @{
2853  */
2854  template<__format::__char _CharT>
2855  struct formatter<const void*, _CharT>
2856  {
2857  formatter() = default;
2858 
2859  constexpr typename basic_format_parse_context<_CharT>::iterator
2860  parse(basic_format_parse_context<_CharT>& __pc)
2861  {
2862  __format::_Spec<_CharT> __spec{};
2863  const auto __last = __pc.end();
2864  auto __first = __pc.begin();
2865 
2866  auto __finalize = [this, &__spec] {
2867  _M_spec = __spec;
2868  };
2869 
2870  auto __finished = [&] {
2871  if (__first == __last || *__first == '}')
2872  {
2873  __finalize();
2874  return true;
2875  }
2876  return false;
2877  };
2878 
2879  if (__finished())
2880  return __first;
2881 
2882  __first = __spec._M_parse_fill_and_align(__first, __last);
2883  if (__finished())
2884  return __first;
2885 
2886 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2887 // P2510R3 Formatting pointers
2888 #if __glibcxx_format >= 202304L
2889  __first = __spec._M_parse_zero_fill(__first, __last);
2890  if (__finished())
2891  return __first;
2892 #endif
2893 
2894  __first = __spec._M_parse_width(__first, __last, __pc);
2895 
2896  if (__first != __last)
2897  {
2898  if (*__first == 'p')
2899  ++__first;
2900 #if __glibcxx_format >= 202304L
2901  else if (*__first == 'P')
2902  {
2903  __spec._M_type = __format::_Pres_P;
2904  ++__first;
2905  }
2906 #endif
2907  }
2908 
2909  if (__finished())
2910  return __first;
2911 
2912  __format::__failed_to_parse_format_spec();
2913  }
2914 
2915  template<typename _Out>
2916  typename basic_format_context<_Out, _CharT>::iterator
2917  format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const
2918  {
2919  auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v);
2920  char __buf[2 + sizeof(__v) * 2];
2921  auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf),
2922  __u, 16);
2923  int __n = __ptr - __buf;
2924  __buf[0] = '0';
2925  __buf[1] = 'x';
2926 #if __glibcxx_format >= 202304L
2927  if (_M_spec._M_type == __format::_Pres_P)
2928  {
2929  __buf[1] = 'X';
2930  for (auto __p = __buf + 2; __p != __ptr; ++__p)
2931 #if __has_builtin(__builtin_toupper)
2932  *__p = __builtin_toupper(*__p);
2933 #else
2934  *__p = std::toupper(*__p);
2935 #endif
2936  }
2937 #endif
2938 
2939  basic_string_view<_CharT> __str;
2940  if constexpr (is_same_v<_CharT, char>)
2941  __str = string_view(__buf, __n);
2942 #ifdef _GLIBCXX_USE_WCHAR_T
2943  else
2944  {
2945  auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
2946  std::__to_wstring_numeric(__buf, __n, __p);
2947  __str = wstring_view(__p, __n);
2948  }
2949 #endif
2950 
2951 #if __glibcxx_format >= 202304L
2952  if (_M_spec._M_zero_fill)
2953  {
2954  size_t __width = _M_spec._M_get_width(__fc);
2955  if (__width <= __str.size())
2956  return __format::__write(__fc.out(), __str);
2957 
2958  auto __out = __fc.out();
2959  // Write "0x" or "0X" prefix before zero-filling.
2960  __out = __format::__write(std::move(__out), __str.substr(0, 2));
2961  __str.remove_prefix(2);
2962  size_t __nfill = __width - __n;
2963  return __format::__write_padded(std::move(__out), __str,
2964  __format::_Align_right,
2965  __nfill, _CharT('0'));
2966  }
2967 #endif
2968 
2969  return __format::__write_padded_as_spec(__str, __n, __fc, _M_spec,
2970  __format::_Align_right);
2971  }
2972 
2973  private:
2974  __format::_Spec<_CharT> _M_spec{};
2975  };
2976 
2977  template<__format::__char _CharT>
2978  struct formatter<void*, _CharT>
2979  {
2980  formatter() = default;
2981 
2982  [[__gnu__::__always_inline__]]
2983  constexpr typename basic_format_parse_context<_CharT>::iterator
2984  parse(basic_format_parse_context<_CharT>& __pc)
2985  { return _M_f.parse(__pc); }
2986 
2987  template<typename _Out>
2988  typename basic_format_context<_Out, _CharT>::iterator
2989  format(void* __v, basic_format_context<_Out, _CharT>& __fc) const
2990  { return _M_f.format(__v, __fc); }
2991 
2992  private:
2993  formatter<const void*, _CharT> _M_f;
2994  };
2995 
2996  template<__format::__char _CharT>
2997  struct formatter<nullptr_t, _CharT>
2998  {
2999  formatter() = default;
3000 
3001  [[__gnu__::__always_inline__]]
3002  constexpr typename basic_format_parse_context<_CharT>::iterator
3003  parse(basic_format_parse_context<_CharT>& __pc)
3004  { return _M_f.parse(__pc); }
3005 
3006  template<typename _Out>
3007  typename basic_format_context<_Out, _CharT>::iterator
3008  format(nullptr_t, basic_format_context<_Out, _CharT>& __fc) const
3009  { return _M_f.format(nullptr, __fc); }
3010 
3011  private:
3012  formatter<const void*, _CharT> _M_f;
3013  };
3014  /// @}
3015 
3016 #if defined _GLIBCXX_USE_WCHAR_T && __glibcxx_format_ranges
3017  // _GLIBCXX_RESOLVE_LIB_DEFECTS
3018  // 3944. Formatters converting sequences of char to sequences of wchar_t
3019 
3020  struct __formatter_disabled
3021  {
3022  __formatter_disabled() = delete; // Cannot format char sequence to wchar_t
3023  __formatter_disabled(const __formatter_disabled&) = delete;
3024  __formatter_disabled& operator=(const __formatter_disabled&) = delete;
3025  };
3026 
3027  template<>
3028  struct formatter<char*, wchar_t>
3029  : private __formatter_disabled { };
3030  template<>
3031  struct formatter<const char*, wchar_t>
3032  : private __formatter_disabled { };
3033  template<size_t _Nm>
3034  struct formatter<char[_Nm], wchar_t>
3035  : private __formatter_disabled { };
3036  template<class _Traits, class _Allocator>
3037  struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t>
3038  : private __formatter_disabled { };
3039  template<class _Traits>
3040  struct formatter<basic_string_view<char, _Traits>, wchar_t>
3041  : private __formatter_disabled { };
3042 #endif
3043 
3044  /// An iterator after the last character written, and the number of
3045  /// characters that would have been written.
3046  template<typename _Out>
3047  struct format_to_n_result
3048  {
3049  _Out out;
3050  iter_difference_t<_Out> size;
3051  };
3052 
3053 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
3054 template<typename, typename> class vector;
3055 _GLIBCXX_END_NAMESPACE_CONTAINER
3056 
3057 /// @cond undocumented
3058 namespace __format
3059 {
3060  template<typename _CharT>
3061  class _Sink_iter
3062  {
3063  _Sink<_CharT>* _M_sink = nullptr;
3064 
3065  public:
3066  using iterator_category = output_iterator_tag;
3067  using value_type = void;
3068  using difference_type = ptrdiff_t;
3069  using pointer = void;
3070  using reference = void;
3071 
3072  _Sink_iter() = default;
3073  _Sink_iter(const _Sink_iter&) = default;
3074  _Sink_iter& operator=(const _Sink_iter&) = default;
3075 
3076  [[__gnu__::__always_inline__]]
3077  explicit constexpr
3078  _Sink_iter(_Sink<_CharT>& __sink) : _M_sink(std::addressof(__sink)) { }
3079 
3080  [[__gnu__::__always_inline__]]
3081  constexpr _Sink_iter&
3082  operator=(_CharT __c)
3083  {
3084  _M_sink->_M_write(__c);
3085  return *this;
3086  }
3087 
3088  [[__gnu__::__always_inline__]]
3089  constexpr _Sink_iter&
3090  operator=(basic_string_view<_CharT> __s)
3091  {
3092  _M_sink->_M_write(__s);
3093  return *this;
3094  }
3095 
3096  [[__gnu__::__always_inline__]]
3097  constexpr _Sink_iter&
3098  operator*() { return *this; }
3099 
3100  [[__gnu__::__always_inline__]]
3101  constexpr _Sink_iter&
3102  operator++() { return *this; }
3103 
3104  [[__gnu__::__always_inline__]]
3105  constexpr _Sink_iter
3106  operator++(int) { return *this; }
3107 
3108  auto
3109  _M_reserve(size_t __n) const
3110  { return _M_sink->_M_reserve(__n); }
3111  };
3112 
3113  // Abstract base class for type-erased character sinks.
3114  // All formatting and output is done via this type's iterator,
3115  // to reduce the number of different template instantiations.
3116  template<typename _CharT>
3117  class _Sink
3118  {
3119  friend class _Sink_iter<_CharT>;
3120 
3121  span<_CharT> _M_span;
3122  typename span<_CharT>::iterator _M_next;
3123 
3124  // Called when the span is full, to make more space available.
3125  // Precondition: _M_next != _M_span.begin()
3126  // Postcondition: _M_next != _M_span.end()
3127  // TODO: remove the precondition? could make overflow handle it.
3128  virtual void _M_overflow() = 0;
3129 
3130  protected:
3131  // Precondition: __span.size() != 0
3132  [[__gnu__::__always_inline__]]
3133  explicit constexpr
3134  _Sink(span<_CharT> __span) noexcept
3135  : _M_span(__span), _M_next(__span.begin())
3136  { }
3137 
3138  // The portion of the span that has been written to.
3139  [[__gnu__::__always_inline__]]
3140  span<_CharT>
3141  _M_used() const noexcept
3142  { return _M_span.first(_M_next - _M_span.begin()); }
3143 
3144  // The portion of the span that has not been written to.
3145  [[__gnu__::__always_inline__]]
3146  constexpr span<_CharT>
3147  _M_unused() const noexcept
3148  { return _M_span.subspan(_M_next - _M_span.begin()); }
3149 
3150  // Use the start of the span as the next write position.
3151  [[__gnu__::__always_inline__]]
3152  constexpr void
3153  _M_rewind() noexcept
3154  { _M_next = _M_span.begin(); }
3155 
3156  // Replace the current output range.
3157  void
3158  _M_reset(span<_CharT> __s, size_t __pos = 0) noexcept
3159  {
3160  _M_span = __s;
3161  _M_next = __s.begin() + __pos;
3162  }
3163 
3164  // Called by the iterator for *it++ = c
3165  constexpr void
3166  _M_write(_CharT __c)
3167  {
3168  *_M_next++ = __c;
3169  if (_M_next - _M_span.begin() == std::ssize(_M_span)) [[unlikely]]
3170  _M_overflow();
3171  }
3172 
3173  constexpr void
3174  _M_write(basic_string_view<_CharT> __s)
3175  {
3176  span __to = _M_unused();
3177  while (__to.size() <= __s.size())
3178  {
3179  __s.copy(__to.data(), __to.size());
3180  _M_next += __to.size();
3181  __s.remove_prefix(__to.size());
3182  _M_overflow();
3183  __to = _M_unused();
3184  }
3185  if (__s.size())
3186  {
3187  __s.copy(__to.data(), __s.size());
3188  _M_next += __s.size();
3189  }
3190  }
3191 
3192  // A successful _Reservation can be used to directly write
3193  // up to N characters to the sink to avoid unwanted buffering.
3194  struct _Reservation
3195  {
3196  // True if the reservation was successful, false otherwise.
3197  explicit operator bool() const noexcept { return _M_sink; }
3198  // A pointer to write directly to the sink.
3199  _CharT* get() const noexcept { return _M_sink->_M_next.operator->(); }
3200  // Add n to the _M_next iterator for the sink.
3201  void _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
3202  _Sink* _M_sink;
3203  };
3204 
3205  // Attempt to reserve space to write n characters to the sink.
3206  // If anything is written to the reservation then there must be a call
3207  // to _M_bump(N2) before any call to another member function of *this,
3208  // where N2 is the number of characters written.
3209  virtual _Reservation
3210  _M_reserve(size_t __n)
3211  {
3212  if (__n <= _M_unused().size())
3213  return { this };
3214 
3215  if (__n <= _M_span.size()) // Cannot meet the request.
3216  {
3217  _M_overflow(); // Make more space available.
3218  if (__n <= _M_unused().size())
3219  return { this };
3220  }
3221  return { nullptr };
3222  }
3223 
3224  // Update the next output position after writing directly to the sink.
3225  // pre: no calls to _M_write or _M_overflow since _M_reserve.
3226  virtual void
3227  _M_bump(size_t __n)
3228  { _M_next += __n; }
3229 
3230  public:
3231  _Sink(const _Sink&) = delete;
3232  _Sink& operator=(const _Sink&) = delete;
3233 
3234  [[__gnu__::__always_inline__]]
3235  constexpr _Sink_iter<_CharT>
3236  out() noexcept
3237  { return _Sink_iter<_CharT>(*this); }
3238  };
3239 
3240 
3241  template<typename _CharT>
3242  class _Fixedbuf_sink final : public _Sink<_CharT>
3243  {
3244  void
3245  _M_overflow() override
3246  {
3247  __glibcxx_assert(false);
3248  this->_M_rewind();
3249  }
3250 
3251  public:
3252  [[__gnu__::__always_inline__]]
3253  constexpr explicit
3254  _Fixedbuf_sink(span<_CharT> __buf)
3255  : _Sink<_CharT>(__buf)
3256  { }
3257 
3258  constexpr basic_string_view<_CharT>
3259  view() const
3260  {
3261  auto __s = this->_M_used();
3262  return basic_string_view<_CharT>(__s.data(), __s.size());
3263  }
3264  };
3265 
3266  // A sink with an internal buffer. This is used to implement concrete sinks.
3267  template<typename _CharT>
3268  class _Buf_sink : public _Sink<_CharT>
3269  {
3270  protected:
3271  _CharT _M_buf[__stackbuf_size<_CharT>];
3272 
3273  [[__gnu__::__always_inline__]]
3274  constexpr
3275  _Buf_sink() noexcept
3276  : _Sink<_CharT>(_M_buf)
3277  { }
3278  };
3279 
3280  using _GLIBCXX_STD_C::vector;
3281 
3282  // A sink that fills a sequence (e.g. std::string, std::vector, std::deque).
3283  // Writes to a buffer then appends that to the sequence when it fills up.
3284  template<typename _Seq>
3285  class _Seq_sink final : public _Buf_sink<typename _Seq::value_type>
3286  {
3287  using _CharT = typename _Seq::value_type;
3288 
3289  _Seq _M_seq;
3290 
3291  // Transfer buffer contents to the sequence, so buffer can be refilled.
3292  void
3293  _M_overflow() override
3294  {
3295  auto __s = this->_M_used();
3296  if (__s.empty()) [[unlikely]]
3297  return; // Nothing in the buffer to transfer to _M_seq.
3298 
3299  // If _M_reserve was called then _M_bump must have been called too.
3300  _GLIBCXX_DEBUG_ASSERT(__s.data() != _M_seq.data());
3301 
3302  if constexpr (__is_specialization_of<_Seq, basic_string>)
3303  _M_seq.append(__s.data(), __s.size());
3304  else
3305  _M_seq.insert(_M_seq.end(), __s.begin(), __s.end());
3306 
3307  // Make the whole of _M_buf available for the next write:
3308  this->_M_rewind();
3309  }
3310 
3311  typename _Sink<_CharT>::_Reservation
3312  _M_reserve(size_t __n) override
3313  {
3314  // We might already have n characters available in this->_M_unused(),
3315  // but the whole point of this function is to be an optimization for
3316  // the std::format("{}", x) case. We want to avoid writing to _M_buf
3317  // and then copying that into a basic_string if possible, so this
3318  // function prefers to create space directly in _M_seq rather than
3319  // using _M_buf.
3320 
3321  if constexpr (__is_specialization_of<_Seq, basic_string>
3322  || __is_specialization_of<_Seq, vector>)
3323  {
3324  // Flush the buffer to _M_seq first (should not be needed).
3325  if (this->_M_used().size()) [[unlikely]]
3326  _Seq_sink::_M_overflow();
3327 
3328  // Expand _M_seq to make __n new characters available:
3329  const auto __sz = _M_seq.size();
3330  if constexpr (is_same_v<string, _Seq> || is_same_v<wstring, _Seq>)
3331  _M_seq.__resize_and_overwrite(__sz + __n,
3332  [](auto, auto __n2) {
3333  return __n2;
3334  });
3335  else
3336  _M_seq.resize(__sz + __n);
3337 
3338  // Set _M_used() to be a span over the original part of _M_seq
3339  // and _M_unused() to be the extra capacity we just created:
3340  this->_M_reset(_M_seq, __sz);
3341  return { this };
3342  }
3343  else // Try to use the base class' buffer.
3344  return _Sink<_CharT>::_M_reserve(__n);
3345  }
3346 
3347  void
3348  _M_bump(size_t __n) override
3349  {
3350  if constexpr (__is_specialization_of<_Seq, basic_string>
3351  || __is_specialization_of<_Seq, vector>)
3352  {
3353  auto __s = this->_M_used();
3354  _GLIBCXX_DEBUG_ASSERT(__s.data() == _M_seq.data());
3355  // Truncate the sequence to the part that was actually written to:
3356  _M_seq.resize(__s.size() + __n);
3357  // Switch back to using buffer:
3358  this->_M_reset(this->_M_buf);
3359  }
3360  }
3361 
3362  public:
3363  // TODO: for SSO string, use SSO buffer as initial span, then switch
3364  // to _M_buf if it overflows? Or even do that for all unused capacity?
3365 
3366  [[__gnu__::__always_inline__]]
3367  _Seq_sink() noexcept(is_nothrow_default_constructible_v<_Seq>)
3368  { }
3369 
3370  _Seq_sink(_Seq&& __s) noexcept(is_nothrow_move_constructible_v<_Seq>)
3371  : _M_seq(std::move(__s))
3372  { }
3373 
3374  using _Sink<_CharT>::out;
3375 
3376  _Seq
3377  get() &&
3378  {
3379  if (this->_M_used().size() != 0)
3380  _Seq_sink::_M_overflow();
3381  return std::move(_M_seq);
3382  }
3383 
3384  // A writable span that views everything written to the sink.
3385  // Will be either a view over _M_seq or the used part of _M_buf.
3386  span<_CharT>
3387  view()
3388  {
3389  auto __s = this->_M_used();
3390  if (_M_seq.size())
3391  {
3392  if (__s.size() != 0)
3393  _Seq_sink::_M_overflow();
3394  return _M_seq;
3395  }
3396  return __s;
3397  }
3398  };
3399 
3400  // A sink that writes to an output iterator.
3401  // Writes to a fixed-size buffer and then flushes to the output iterator
3402  // when the buffer fills up.
3403  template<typename _CharT, typename _OutIter>
3404  class _Iter_sink : public _Buf_sink<_CharT>
3405  {
3406  _OutIter _M_out;
3407  iter_difference_t<_OutIter> _M_max;
3408 
3409  protected:
3410  size_t _M_count = 0;
3411 
3412  void
3413  _M_overflow() override
3414  {
3415  auto __s = this->_M_used();
3416  if (_M_max < 0) // No maximum.
3417  _M_out = ranges::copy(__s, std::move(_M_out)).out;
3418  else if (_M_count < static_cast<size_t>(_M_max))
3419  {
3420  auto __max = _M_max - _M_count;
3421  span<_CharT> __first;
3422  if (__max < __s.size())
3423  __first = __s.first(static_cast<size_t>(__max));
3424  else
3425  __first = __s;
3426  _M_out = ranges::copy(__first, std::move(_M_out)).out;
3427  }
3428  this->_M_rewind();
3429  _M_count += __s.size();
3430  }
3431 
3432  public:
3433  [[__gnu__::__always_inline__]]
3434  explicit
3435  _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __max = -1)
3436  : _M_out(std::move(__out)), _M_max(__max)
3437  { }
3438 
3439  using _Sink<_CharT>::out;
3440 
3441  format_to_n_result<_OutIter>
3442  _M_finish() &&
3443  {
3444  if (this->_M_used().size() != 0)
3445  _Iter_sink::_M_overflow();
3446  iter_difference_t<_OutIter> __count(_M_count);
3447  return { std::move(_M_out), __count };
3448  }
3449  };
3450 
3451  // Partial specialization for contiguous iterators.
3452  // No buffer is used, characters are written straight to the iterator.
3453  // We do not know the size of the output range, so the span size just grows
3454  // as needed. The end of the span might be an invalid pointer outside the
3455  // valid range, but we never actually call _M_span.end(). This class does
3456  // not introduce any invalid pointer arithmetic or overflows that would not
3457  // have happened anyway.
3458  template<typename _CharT, contiguous_iterator _OutIter>
3459  requires same_as<iter_value_t<_OutIter>, _CharT>
3460  class _Iter_sink<_CharT, _OutIter> : public _Sink<_CharT>
3461  {
3462  _OutIter _M_first;
3463  iter_difference_t<_OutIter> _M_max = -1;
3464  protected:
3465  size_t _M_count = 0;
3466  private:
3467  _CharT _M_buf[64]; // Write here after outputting _M_max characters.
3468 
3469  protected:
3470  void
3471  _M_overflow() override
3472  {
3473  if (this->_M_unused().size() != 0)
3474  return; // No need to switch to internal buffer yet.
3475 
3476  auto __s = this->_M_used();
3477 
3478  if (_M_max >= 0)
3479  {
3480  _M_count += __s.size();
3481  // Span was already sized for the maximum character count,
3482  // if it overflows then any further output must go to the
3483  // internal buffer, to be discarded.
3484  this->_M_reset(this->_M_buf);
3485  }
3486  else
3487  {
3488  // No maximum character count. Just extend the span to allow
3489  // writing more characters to it.
3490  this->_M_reset({__s.data(), __s.size() + 1024}, __s.size());
3491  }
3492  }
3493 
3494  typename _Sink<_CharT>::_Reservation
3495  _M_reserve(size_t __n) final
3496  {
3497  auto __avail = this->_M_unused();
3498  if (__n > __avail.size())
3499  {
3500  if (_M_max >= 0)
3501  return {}; // cannot grow
3502 
3503  auto __s = this->_M_used();
3504  this->_M_reset({__s.data(), __s.size() + __n}, __s.size());
3505  }
3506  return { this };
3507  }
3508 
3509  private:
3510  static span<_CharT>
3511  _S_make_span(_CharT* __ptr, iter_difference_t<_OutIter> __n,
3512  span<_CharT> __buf) noexcept
3513  {
3514  if (__n == 0)
3515  return __buf; // Only write to the internal buffer.
3516 
3517  if (__n > 0)
3518  {
3519  if constexpr (!is_integral_v<iter_difference_t<_OutIter>>
3520  || sizeof(__n) > sizeof(size_t))
3521  {
3522  // __int128 or __detail::__max_diff_type
3523  auto __m = iter_difference_t<_OutIter>((size_t)-1);
3524  if (__n > __m)
3525  __n = __m;
3526  }
3527  return {__ptr, (size_t)__n};
3528  }
3529 
3530 #if __has_builtin(__builtin_dynamic_object_size)
3531  if (size_t __bytes = __builtin_dynamic_object_size(__ptr, 2))
3532  return {__ptr, __bytes / sizeof(_CharT)};
3533 #endif
3534  // Avoid forming a pointer to a different memory page.
3535  const auto __off = reinterpret_cast<__UINTPTR_TYPE__>(__ptr) % 1024;
3536  __n = (1024 - __off) / sizeof(_CharT);
3537  if (__n > 0) [[likely]]
3538  return {__ptr, static_cast<size_t>(__n)};
3539  else // Misaligned/packed buffer of wchar_t?
3540  return {__ptr, 1};
3541  }
3542 
3543  public:
3544  explicit
3545  _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __n = -1) noexcept
3546  : _Sink<_CharT>(_S_make_span(std::to_address(__out), __n, _M_buf)),
3547  _M_first(__out), _M_max(__n)
3548  { }
3549 
3550  format_to_n_result<_OutIter>
3551  _M_finish() &&
3552  {
3553  auto __s = this->_M_used();
3554  if (__s.data() == _M_buf)
3555  {
3556  // Switched to internal buffer, so must have written _M_max.
3557  iter_difference_t<_OutIter> __count(_M_count + __s.size());
3558  return { _M_first + _M_max, __count };
3559  }
3560  else // Not using internal buffer yet
3561  {
3562  iter_difference_t<_OutIter> __count(__s.size());
3563  return { _M_first + __count, __count };
3564  }
3565  }
3566  };
3567 
3568  enum _Arg_t : unsigned char {
3569  _Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull,
3570  _Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr, _Arg_handle,
3571  _Arg_i128, _Arg_u128,
3572  _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, // These are unused.
3573 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3574  _Arg_next_value_,
3575  _Arg_f128 = _Arg_ldbl,
3576  _Arg_ibm128 = _Arg_next_value_,
3577 #else
3578  _Arg_f128,
3579 #endif
3580  _Arg_max_
3581  };
3582 
3583  template<typename _Context>
3584  struct _Arg_value
3585  {
3586  using _CharT = typename _Context::char_type;
3587 
3588  struct _HandleBase
3589  {
3590  const void* _M_ptr;
3591  void (*_M_func)();
3592  };
3593 
3594  union
3595  {
3596  monostate _M_none;
3597  bool _M_bool;
3598  _CharT _M_c;
3599  int _M_i;
3600  unsigned _M_u;
3601  long long _M_ll;
3602  unsigned long long _M_ull;
3603  float _M_flt;
3604  double _M_dbl;
3605 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // No long double if it's ambiguous.
3606  long double _M_ldbl;
3607 #endif
3608  const _CharT* _M_str;
3609  basic_string_view<_CharT> _M_sv;
3610  const void* _M_ptr;
3611  _HandleBase _M_handle;
3612 #ifdef __SIZEOF_INT128__
3613  __int128 _M_i128;
3614  unsigned __int128 _M_u128;
3615 #endif
3616 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3617  __ieee128 _M_f128;
3618  __ibm128 _M_ibm128;
3619 #elif _GLIBCXX_FORMAT_F128 == 2
3620  __float128_t _M_f128;
3621 #endif
3622  };
3623 
3624  [[__gnu__::__always_inline__]]
3625  _Arg_value() : _M_none() { }
3626 
3627 #if 0
3628  template<typename _Tp>
3629  _Arg_value(in_place_type_t<_Tp>, _Tp __val)
3630  { _S_get<_Tp>() = __val; }
3631 #endif
3632 
3633  template<typename _Tp, typename _Self>
3634  [[__gnu__::__always_inline__]]
3635  static auto&
3636  _S_get(_Self& __u) noexcept
3637  {
3638  if constexpr (is_same_v<_Tp, bool>)
3639  return __u._M_bool;
3640  else if constexpr (is_same_v<_Tp, _CharT>)
3641  return __u._M_c;
3642  else if constexpr (is_same_v<_Tp, int>)
3643  return __u._M_i;
3644  else if constexpr (is_same_v<_Tp, unsigned>)
3645  return __u._M_u;
3646  else if constexpr (is_same_v<_Tp, long long>)
3647  return __u._M_ll;
3648  else if constexpr (is_same_v<_Tp, unsigned long long>)
3649  return __u._M_ull;
3650  else if constexpr (is_same_v<_Tp, float>)
3651  return __u._M_flt;
3652  else if constexpr (is_same_v<_Tp, double>)
3653  return __u._M_dbl;
3654 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3655  else if constexpr (is_same_v<_Tp, long double>)
3656  return __u._M_ldbl;
3657 #else
3658  else if constexpr (is_same_v<_Tp, __ieee128>)
3659  return __u._M_f128;
3660  else if constexpr (is_same_v<_Tp, __ibm128>)
3661  return __u._M_ibm128;
3662 #endif
3663  else if constexpr (is_same_v<_Tp, const _CharT*>)
3664  return __u._M_str;
3665  else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
3666  return __u._M_sv;
3667  else if constexpr (is_same_v<_Tp, const void*>)
3668  return __u._M_ptr;
3669 #ifdef __SIZEOF_INT128__
3670  else if constexpr (is_same_v<_Tp, __int128>)
3671  return __u._M_i128;
3672  else if constexpr (is_same_v<_Tp, unsigned __int128>)
3673  return __u._M_u128;
3674 #endif
3675 #if _GLIBCXX_FORMAT_F128 == 2
3676  else if constexpr (is_same_v<_Tp, __float128_t>)
3677  return __u._M_f128;
3678 #endif
3679  else if constexpr (derived_from<_Tp, _HandleBase>)
3680  return static_cast<_Tp&>(__u._M_handle);
3681  // Otherwise, ill-formed.
3682  }
3683 
3684  template<typename _Tp>
3685  [[__gnu__::__always_inline__]]
3686  auto&
3687  _M_get() noexcept
3688  { return _S_get<_Tp>(*this); }
3689 
3690  template<typename _Tp>
3691  [[__gnu__::__always_inline__]]
3692  const auto&
3693  _M_get() const noexcept
3694  { return _S_get<_Tp>(*this); }
3695 
3696  template<typename _Tp>
3697  [[__gnu__::__always_inline__]]
3698  void
3699  _M_set(_Tp __v) noexcept
3700  {
3701  if constexpr (derived_from<_Tp, _HandleBase>)
3702  std::construct_at(&_M_handle, __v);
3703  else
3704  _S_get<_Tp>(*this) = __v;
3705  }
3706  };
3707 
3708  // [format.arg.store], class template format-arg-store
3709  template<typename _Context, typename... _Args>
3710  class _Arg_store;
3711 
3712  template<typename _Visitor, typename _Ctx>
3713  decltype(auto) __visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
3714 
3715  template<typename _Ch, typename _Tp>
3716  consteval _Arg_t
3717  __to_arg_t_enum() noexcept;
3718 } // namespace __format
3719 /// @endcond
3720 
3721  template<typename _Context>
3722  class basic_format_arg
3723  {
3724  using _CharT = typename _Context::char_type;
3725 
3726  template<typename _Tp>
3727  static constexpr bool __formattable
3728  = __format::__formattable_with<_Tp, _Context>;
3729 
3730  public:
3731  class handle : public __format::_Arg_value<_Context>::_HandleBase
3732  {
3733  using _Base = typename __format::_Arg_value<_Context>::_HandleBase;
3734 
3735  // Format as const if possible, to reduce instantiations.
3736  template<typename _Tp>
3737  using __maybe_const_t
3738  = __conditional_t<__formattable<const _Tp>, const _Tp, _Tp>;
3739 
3740  template<typename _Tq>
3741  static void
3742  _S_format(basic_format_parse_context<_CharT>& __parse_ctx,
3743  _Context& __format_ctx, const void* __ptr)
3744  {
3745  using _Td = remove_const_t<_Tq>;
3746  typename _Context::template formatter_type<_Td> __f;
3747  __parse_ctx.advance_to(__f.parse(__parse_ctx));
3748  _Tq& __val = *const_cast<_Tq*>(static_cast<const _Td*>(__ptr));
3749  __format_ctx.advance_to(__f.format(__val, __format_ctx));
3750  }
3751 
3752  template<typename _Tp>
3753  explicit
3754  handle(_Tp& __val) noexcept
3755  {
3756  this->_M_ptr = __builtin_addressof(__val);
3757  auto __func = _S_format<__maybe_const_t<_Tp>>;
3758  this->_M_func = reinterpret_cast<void(*)()>(__func);
3759  }
3760 
3761  friend class basic_format_arg<_Context>;
3762 
3763  public:
3764  handle(const handle&) = default;
3765  handle& operator=(const handle&) = default;
3766 
3767  [[__gnu__::__always_inline__]]
3768  void
3769  format(basic_format_parse_context<_CharT>& __pc, _Context& __fc) const
3770  {
3771  using _Func = void(*)(basic_format_parse_context<_CharT>&,
3772  _Context&, const void*);
3773  auto __f = reinterpret_cast<_Func>(this->_M_func);
3774  __f(__pc, __fc, this->_M_ptr);
3775  }
3776  };
3777 
3778  [[__gnu__::__always_inline__]]
3779  basic_format_arg() noexcept : _M_type(__format::_Arg_none) { }
3780 
3781  [[nodiscard,__gnu__::__always_inline__]]
3782  explicit operator bool() const noexcept
3783  { return _M_type != __format::_Arg_none; }
3784 
3785 #if __cpp_lib_format >= 202306L // >= C++26
3786  template<typename _Visitor>
3787  decltype(auto)
3788  visit(this basic_format_arg __arg, _Visitor&& __vis)
3789  { return __arg._M_visit_user(std::forward<_Visitor>(__vis), __arg._M_type); }
3790 
3791  template<typename _Res, typename _Visitor>
3792  _Res
3793  visit(this basic_format_arg __arg, _Visitor&& __vis)
3794  { return __arg._M_visit_user(std::forward<_Visitor>(__vis), __arg._M_type); }
3795 #endif
3796 
3797  private:
3798  template<typename _Ctx>
3799  friend class basic_format_args;
3800 
3801  template<typename _Ctx, typename... _Args>
3802  friend class __format::_Arg_store;
3803 
3804  static_assert(is_trivially_copyable_v<__format::_Arg_value<_Context>>);
3805 
3806  __format::_Arg_value<_Context> _M_val;
3807  __format::_Arg_t _M_type;
3808 
3809  // Transform incoming argument type to the type stored in _Arg_value.
3810  // e.g. short -> int, std::string -> std::string_view,
3811  // char[3] -> const char*.
3812  template<typename _Tp>
3813  static consteval auto
3814  _S_to_arg_type()
3815  {
3816  using _Td = remove_const_t<_Tp>;
3817  if constexpr (is_same_v<_Td, bool>)
3818  return type_identity<bool>();
3819  else if constexpr (is_same_v<_Td, _CharT>)
3820  return type_identity<_CharT>();
3821  else if constexpr (is_same_v<_Td, char> && is_same_v<_CharT, wchar_t>)
3822  return type_identity<_CharT>();
3823 #ifdef __SIZEOF_INT128__ // Check before signed/unsigned integer
3824  else if constexpr (is_same_v<_Td, __int128>)
3825  return type_identity<__int128>();
3826  else if constexpr (is_same_v<_Td, unsigned __int128>)
3827  return type_identity<unsigned __int128>();
3828 #endif
3829  else if constexpr (__is_signed_integer<_Td>::value)
3830  {
3831  if constexpr (sizeof(_Td) <= sizeof(int))
3832  return type_identity<int>();
3833  else if constexpr (sizeof(_Td) <= sizeof(long long))
3834  return type_identity<long long>();
3835  }
3836  else if constexpr (__is_unsigned_integer<_Td>::value)
3837  {
3838  if constexpr (sizeof(_Td) <= sizeof(unsigned))
3839  return type_identity<unsigned>();
3840  else if constexpr (sizeof(_Td) <= sizeof(unsigned long long))
3841  return type_identity<unsigned long long>();
3842  }
3843  else if constexpr (is_same_v<_Td, float>)
3844  return type_identity<float>();
3845  else if constexpr (is_same_v<_Td, double>)
3846  return type_identity<double>();
3847 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3848  else if constexpr (is_same_v<_Td, long double>)
3849  return type_identity<long double>();
3850 #else
3851  else if constexpr (is_same_v<_Td, __ibm128>)
3852  return type_identity<__ibm128>();
3853  else if constexpr (is_same_v<_Td, __ieee128>)
3854  return type_identity<__ieee128>();
3855 #endif
3856 
3857 #if defined(__FLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
3858  else if constexpr (is_same_v<_Td, _Float16>)
3859  return type_identity<float>();
3860 #endif
3861 
3862 #if defined(__BFLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
3863  else if constexpr (is_same_v<_Td, decltype(0.0bf16)>)
3864  return type_identity<float>();
3865 #endif
3866 
3867 #if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
3868  else if constexpr (is_same_v<_Td, _Float32>)
3869  return type_identity<float>();
3870 #endif
3871 
3872 #if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
3873  else if constexpr (is_same_v<_Td, _Float64>)
3874  return type_identity<double>();
3875 #endif
3876 
3877 #if _GLIBCXX_FORMAT_F128
3878 # if __FLT128_DIG__
3879  else if constexpr (is_same_v<_Td, _Float128>)
3880  return type_identity<__format::__float128_t>();
3881 # endif
3882 # if __SIZEOF_FLOAT128__
3883  else if constexpr (is_same_v<_Td, __float128>)
3884  return type_identity<__format::__float128_t>();
3885 # endif
3886 #endif
3887  else if constexpr (__is_specialization_of<_Td, basic_string_view>
3888  || __is_specialization_of<_Td, basic_string>)
3889  {
3890  if constexpr (is_same_v<typename _Td::value_type, _CharT>)
3891  return type_identity<basic_string_view<_CharT>>();
3892  else
3893  return type_identity<handle>();
3894  }
3895  else if constexpr (is_same_v<decay_t<_Td>, const _CharT*>)
3896  return type_identity<const _CharT*>();
3897  else if constexpr (is_same_v<decay_t<_Td>, _CharT*>)
3898  return type_identity<const _CharT*>();
3899  else if constexpr (is_void_v<remove_pointer_t<_Td>>)
3900  return type_identity<const void*>();
3901  else if constexpr (is_same_v<_Td, nullptr_t>)
3902  return type_identity<const void*>();
3903  else
3904  return type_identity<handle>();
3905  }
3906 
3907  // Transform a formattable type to the appropriate storage type.
3908  template<typename _Tp>
3909  using _Normalize = typename decltype(_S_to_arg_type<_Tp>())::type;
3910 
3911  // Get the _Arg_t value corresponding to a normalized type.
3912  template<typename _Tp>
3913  static consteval __format::_Arg_t
3914  _S_to_enum()
3915  {
3916  using namespace __format;
3917  if constexpr (is_same_v<_Tp, bool>)
3918  return _Arg_bool;
3919  else if constexpr (is_same_v<_Tp, _CharT>)
3920  return _Arg_c;
3921  else if constexpr (is_same_v<_Tp, int>)
3922  return _Arg_i;
3923  else if constexpr (is_same_v<_Tp, unsigned>)
3924  return _Arg_u;
3925  else if constexpr (is_same_v<_Tp, long long>)
3926  return _Arg_ll;
3927  else if constexpr (is_same_v<_Tp, unsigned long long>)
3928  return _Arg_ull;
3929  else if constexpr (is_same_v<_Tp, float>)
3930  return _Arg_flt;
3931  else if constexpr (is_same_v<_Tp, double>)
3932  return _Arg_dbl;
3933 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
3934  else if constexpr (is_same_v<_Tp, long double>)
3935  return _Arg_ldbl;
3936 #else
3937  // Don't use _Arg_ldbl for this target, it's ambiguous.
3938  else if constexpr (is_same_v<_Tp, __ibm128>)
3939  return _Arg_ibm128;
3940  else if constexpr (is_same_v<_Tp, __ieee128>)
3941  return _Arg_f128;
3942 #endif
3943  else if constexpr (is_same_v<_Tp, const _CharT*>)
3944  return _Arg_str;
3945  else if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
3946  return _Arg_sv;
3947  else if constexpr (is_same_v<_Tp, const void*>)
3948  return _Arg_ptr;
3949 #ifdef __SIZEOF_INT128__
3950  else if constexpr (is_same_v<_Tp, __int128>)
3951  return _Arg_i128;
3952  else if constexpr (is_same_v<_Tp, unsigned __int128>)
3953  return _Arg_u128;
3954 #endif
3955 
3956 #if _GLIBCXX_FORMAT_F128 == 2
3957  else if constexpr (is_same_v<_Tp, __format::__float128_t>)
3958  return _Arg_f128;
3959 #endif
3960  else if constexpr (is_same_v<_Tp, handle>)
3961  return _Arg_handle;
3962  }
3963 
3964  template<typename _Tp>
3965  void
3966  _M_set(_Tp __v) noexcept
3967  {
3968  _M_type = _S_to_enum<_Tp>();
3969  _M_val._M_set(__v);
3970  }
3971 
3972  template<typename _Tp>
3973  requires __format::__formattable_with<_Tp, _Context>
3974  explicit
3975  basic_format_arg(_Tp& __v) noexcept
3976  {
3977  using _Td = _Normalize<_Tp>;
3978  if constexpr (is_same_v<_Td, basic_string_view<_CharT>>)
3979  _M_set(_Td{__v.data(), __v.size()});
3980  else if constexpr (is_same_v<remove_const_t<_Tp>, char>
3981  && is_same_v<_CharT, wchar_t>)
3982  _M_set(static_cast<_Td>(static_cast<unsigned char>(__v)));
3983  else
3984  _M_set(static_cast<_Td>(__v));
3985  }
3986 
3987  template<typename _Ctx, typename... _Argz>
3988  friend auto
3989  make_format_args(_Argz&...) noexcept;
3990 
3991  template<typename _Visitor, typename _Ctx>
3992  friend decltype(auto)
3993  visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx>);
3994 
3995  template<typename _Visitor, typename _Ctx>
3996  friend decltype(auto)
3997  __format::__visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
3998 
3999  template<typename _Ch, typename _Tp>
4000  friend consteval __format::_Arg_t
4001  __format::__to_arg_t_enum() noexcept;
4002 
4003  template<typename _Visitor>
4004  decltype(auto)
4005  _M_visit(_Visitor&& __vis, __format::_Arg_t __type)
4006  {
4007  using namespace __format;
4008  switch (__type)
4009  {
4010  case _Arg_none:
4011  return std::forward<_Visitor>(__vis)(_M_val._M_none);
4012  case _Arg_bool:
4013  return std::forward<_Visitor>(__vis)(_M_val._M_bool);
4014  case _Arg_c:
4015  return std::forward<_Visitor>(__vis)(_M_val._M_c);
4016  case _Arg_i:
4017  return std::forward<_Visitor>(__vis)(_M_val._M_i);
4018  case _Arg_u:
4019  return std::forward<_Visitor>(__vis)(_M_val._M_u);
4020  case _Arg_ll:
4021  return std::forward<_Visitor>(__vis)(_M_val._M_ll);
4022  case _Arg_ull:
4023  return std::forward<_Visitor>(__vis)(_M_val._M_ull);
4024 #if __glibcxx_to_chars // FIXME: need to be able to format these types!
4025  case _Arg_flt:
4026  return std::forward<_Visitor>(__vis)(_M_val._M_flt);
4027  case _Arg_dbl:
4028  return std::forward<_Visitor>(__vis)(_M_val._M_dbl);
4029 #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
4030  case _Arg_ldbl:
4031  return std::forward<_Visitor>(__vis)(_M_val._M_ldbl);
4032 #else
4033  case _Arg_f128:
4034  return std::forward<_Visitor>(__vis)(_M_val._M_f128);
4035  case _Arg_ibm128:
4036  return std::forward<_Visitor>(__vis)(_M_val._M_ibm128);
4037 #endif
4038 #endif
4039  case _Arg_str:
4040  return std::forward<_Visitor>(__vis)(_M_val._M_str);
4041  case _Arg_sv:
4042  return std::forward<_Visitor>(__vis)(_M_val._M_sv);
4043  case _Arg_ptr:
4044  return std::forward<_Visitor>(__vis)(_M_val._M_ptr);
4045  case _Arg_handle:
4046  {
4047  auto& __h = static_cast<handle&>(_M_val._M_handle);
4048  return std::forward<_Visitor>(__vis)(__h);
4049  }
4050 #ifdef __SIZEOF_INT128__
4051  case _Arg_i128:
4052  return std::forward<_Visitor>(__vis)(_M_val._M_i128);
4053  case _Arg_u128:
4054  return std::forward<_Visitor>(__vis)(_M_val._M_u128);
4055 #endif
4056 
4057 #if _GLIBCXX_FORMAT_F128 == 2
4058  case _Arg_f128:
4059  return std::forward<_Visitor>(__vis)(_M_val._M_f128);
4060 #endif
4061 
4062  default:
4063  // _Arg_f16 etc.
4064  __builtin_unreachable();
4065  }
4066  }
4067 
4068  template<typename _Visitor>
4069  decltype(auto)
4070  _M_visit_user(_Visitor&& __vis, __format::_Arg_t __type)
4071  {
4072  return _M_visit([&__vis]<typename _Tp>(_Tp& __val) -> decltype(auto)
4073  {
4074  constexpr bool __user_facing = __is_one_of<_Tp,
4075  monostate, bool, _CharT,
4076  int, unsigned int, long long int, unsigned long long int,
4077  float, double, long double,
4078  const _CharT*, basic_string_view<_CharT>,
4079  const void*, handle>::value;
4080  if constexpr (__user_facing)
4081  return std::forward<_Visitor>(__vis)(__val);
4082  else
4083  {
4084  handle __h(__val);
4085  return std::forward<_Visitor>(__vis)(__h);
4086  }
4087  }, __type);
4088  }
4089  };
4090 
4091  template<typename _Visitor, typename _Context>
4092  _GLIBCXX26_DEPRECATED_SUGGEST("std::basic_format_arg::visit")
4093  inline decltype(auto)
4094  visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
4095  {
4096  return __arg._M_visit_user(std::forward<_Visitor>(__vis), __arg._M_type);
4097  }
4098 
4099 /// @cond undocumented
4100 namespace __format
4101 {
4102  template<typename _Visitor, typename _Ctx>
4103  inline decltype(auto)
4104  __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg)
4105  {
4106  return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type);
4107  }
4108 
4109  struct _WidthPrecVisitor
4110  {
4111  template<typename _Tp>
4112  size_t
4113  operator()(_Tp& __arg) const
4114  {
4115  if constexpr (is_same_v<_Tp, monostate>)
4116  __format::__invalid_arg_id_in_format_string();
4117  // _GLIBCXX_RESOLVE_LIB_DEFECTS
4118  // 3720. Restrict the valid types of arg-id for width and precision
4119  // 3721. Allow an arg-id with a value of zero for width
4120  else if constexpr (sizeof(_Tp) <= sizeof(long long))
4121  {
4122  // _GLIBCXX_RESOLVE_LIB_DEFECTS
4123  // 3720. Restrict the valid types of arg-id for width and precision
4124  if constexpr (__is_unsigned_integer<_Tp>::value)
4125  return __arg;
4126  else if constexpr (__is_signed_integer<_Tp>::value)
4127  if (__arg >= 0)
4128  return __arg;
4129  }
4130  __throw_format_error("format error: argument used for width or "
4131  "precision must be a non-negative integer");
4132  }
4133  };
4134 
4135 #pragma GCC diagnostic push
4136 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
4137  template<typename _Context>
4138  inline size_t
4139  __int_from_arg(const basic_format_arg<_Context>& __arg)
4140  { return __format::__visit_format_arg(_WidthPrecVisitor(), __arg); }
4141 
4142  // Pack _Arg_t enum values into a single 60-bit integer.
4143  template<int _Bits, size_t _Nm>
4144  constexpr auto
4145  __pack_arg_types(const array<_Arg_t, _Nm>& __types)
4146  {
4147  __UINT64_TYPE__ __packed_types = 0;
4148  for (auto __i = __types.rbegin(); __i != __types.rend(); ++__i)
4149  __packed_types = (__packed_types << _Bits) | *__i;
4150  return __packed_types;
4151  }
4152 } // namespace __format
4153 /// @endcond
4154 
4155  template<typename _Context>
4156  class basic_format_args
4157  {
4158  static constexpr int _S_packed_type_bits = 5; // _Arg_t values [0,20]
4159  static constexpr int _S_packed_type_mask = 0b11111;
4160  static constexpr int _S_max_packed_args = 12;
4161 
4162  static_assert( __format::_Arg_max_ <= (1 << _S_packed_type_bits) );
4163 
4164  template<typename... _Args>
4165  using _Store = __format::_Arg_store<_Context, _Args...>;
4166 
4167  template<typename _Ctx, typename... _Args>
4168  friend class __format::_Arg_store;
4169 
4170  using uint64_t = __UINT64_TYPE__;
4171  using _Format_arg = basic_format_arg<_Context>;
4172  using _Format_arg_val = __format::_Arg_value<_Context>;
4173 
4174  // If args are packed then the number of args is in _M_packed_size and
4175  // the packed types are in _M_unpacked_size, accessed via _M_type(i).
4176  // If args are not packed then the number of args is in _M_unpacked_size
4177  // and _M_packed_size is zero.
4178  uint64_t _M_packed_size : 4;
4179  uint64_t _M_unpacked_size : 60;
4180 
4181  union {
4182  const _Format_arg_val* _M_values; // Active when _M_packed_size != 0
4183  const _Format_arg* _M_args; // Active when _M_packed_size == 0
4184  };
4185 
4186  size_t
4187  _M_size() const noexcept
4188  { return _M_packed_size ? _M_packed_size : _M_unpacked_size; }
4189 
4190  typename __format::_Arg_t
4191  _M_type(size_t __i) const noexcept
4192  {
4193  uint64_t __t = _M_unpacked_size >> (__i * _S_packed_type_bits);
4194  return static_cast<__format::_Arg_t>(__t & _S_packed_type_mask);
4195  }
4196 
4197  template<typename _Ctx, typename... _Args>
4198  friend auto
4199  make_format_args(_Args&...) noexcept;
4200 
4201  // An array of _Arg_t enums corresponding to _Args...
4202  template<typename... _Args>
4203  static consteval array<__format::_Arg_t, sizeof...(_Args)>
4204  _S_types_to_pack()
4205  { return {_Format_arg::template _S_to_enum<_Args>()...}; }
4206 
4207  public:
4208  template<typename... _Args>
4209  basic_format_args(const _Store<_Args...>& __store) noexcept;
4210 
4211  [[nodiscard,__gnu__::__always_inline__]]
4212  basic_format_arg<_Context>
4213  get(size_t __i) const noexcept
4214  {
4215  basic_format_arg<_Context> __arg;
4216  if (__i < _M_packed_size)
4217  {
4218  __arg._M_type = _M_type(__i);
4219  __arg._M_val = _M_values[__i];
4220  }
4221  else if (_M_packed_size == 0 && __i < _M_unpacked_size)
4222  __arg = _M_args[__i];
4223  return __arg;
4224  }
4225  };
4226 
4227  // _GLIBCXX_RESOLVE_LIB_DEFECTS
4228  // 3810. CTAD for std::basic_format_args
4229  template<typename _Context, typename... _Args>
4230  basic_format_args(__format::_Arg_store<_Context, _Args...>)
4231  -> basic_format_args<_Context>;
4232 
4233  template<typename _Context, typename... _Args>
4234  auto
4235  make_format_args(_Args&... __fmt_args) noexcept;
4236 
4237  // An array of type-erased formatting arguments.
4238  template<typename _Context, typename... _Args>
4239  class __format::_Arg_store
4240  {
4241  friend std::basic_format_args<_Context>;
4242 
4243  template<typename _Ctx, typename... _Argz>
4244  friend auto std::
4245 #if _GLIBCXX_INLINE_VERSION
4246  __8:: // Needed for PR c++/59256
4247 #endif
4248  make_format_args(_Argz&...) noexcept;
4249 
4250  // For a sufficiently small number of arguments we only store values.
4251  // basic_format_args can get the types from the _Args pack.
4252  static constexpr bool _S_values_only
4253  = sizeof...(_Args) <= basic_format_args<_Context>::_S_max_packed_args;
4254 
4255  using _Element_t
4256  = __conditional_t<_S_values_only,
4257  __format::_Arg_value<_Context>,
4258  basic_format_arg<_Context>>;
4259 
4260  _Element_t _M_args[sizeof...(_Args)];
4261 
4262  template<typename _Tp>
4263  static _Element_t
4264  _S_make_elt(_Tp& __v)
4265  {
4266  using _Tq = remove_const_t<_Tp>;
4267  using _CharT = typename _Context::char_type;
4268  static_assert(is_default_constructible_v<formatter<_Tq, _CharT>>,
4269  "std::formatter must be specialized for the type "
4270  "of each format arg");
4271  using __format::__formattable_with;
4272  if constexpr (is_const_v<_Tp>)
4273  if constexpr (!__formattable_with<_Tp, _Context>)
4274  if constexpr (__formattable_with<_Tq, _Context>)
4275  static_assert(__formattable_with<_Tp, _Context>,
4276  "format arg must be non-const because its "
4277  "std::formatter specialization has a "
4278  "non-const reference parameter");
4279  basic_format_arg<_Context> __arg(__v);
4280  if constexpr (_S_values_only)
4281  return __arg._M_val;
4282  else
4283  return __arg;
4284  }
4285 
4286  template<typename... _Tp>
4287  requires (sizeof...(_Tp) == sizeof...(_Args))
4288  [[__gnu__::__always_inline__]]
4289  _Arg_store(_Tp&... __a) noexcept
4290  : _M_args{_S_make_elt(__a)...}
4291  { }
4292  };
4293 
4294  template<typename _Context>
4295  class __format::_Arg_store<_Context>
4296  { };
4297 
4298  template<typename _Context>
4299  template<typename... _Args>
4300  inline
4301  basic_format_args<_Context>::
4302  basic_format_args(const _Store<_Args...>& __store) noexcept
4303  {
4304  if constexpr (sizeof...(_Args) == 0)
4305  {
4306  _M_packed_size = 0;
4307  _M_unpacked_size = 0;
4308  _M_args = nullptr;
4309  }
4310  else if constexpr (sizeof...(_Args) <= _S_max_packed_args)
4311  {
4312  // The number of packed arguments:
4313  _M_packed_size = sizeof...(_Args);
4314  // The packed type enums:
4315  _M_unpacked_size
4316  = __format::__pack_arg_types<_S_packed_type_bits>(_S_types_to_pack<_Args...>());
4317  // The _Arg_value objects.
4318  _M_values = __store._M_args;
4319  }
4320  else
4321  {
4322  // No packed arguments:
4323  _M_packed_size = 0;
4324  // The number of unpacked arguments:
4325  _M_unpacked_size = sizeof...(_Args);
4326  // The basic_format_arg objects:
4327  _M_args = __store._M_args;
4328  }
4329  }
4330 
4331  /// Capture formatting arguments for use by `std::vformat`.
4332  template<typename _Context = format_context, typename... _Args>
4333  [[nodiscard,__gnu__::__always_inline__]]
4334  inline auto
4335  make_format_args(_Args&... __fmt_args) noexcept
4336  {
4337  using _Fmt_arg = basic_format_arg<_Context>;
4338  using _Store = __format::_Arg_store<_Context, typename _Fmt_arg::template
4339  _Normalize<_Args>...>;
4340  return _Store(__fmt_args...);
4341  }
4342 
4343 #ifdef _GLIBCXX_USE_WCHAR_T
4344  /// Capture formatting arguments for use by `std::vformat` (for wide output).
4345  template<typename... _Args>
4346  [[nodiscard,__gnu__::__always_inline__]]
4347  inline auto
4348  make_wformat_args(_Args&... __args) noexcept
4349  { return std::make_format_args<wformat_context>(__args...); }
4350 #endif
4351 
4352 /// @cond undocumented
4353 namespace __format
4354 {
4355  template<typename _Out, typename _CharT, typename _Context>
4356  _Out
4357  __do_vformat_to(_Out, basic_string_view<_CharT>,
4358  const basic_format_args<_Context>&,
4359  const locale* = nullptr);
4360 
4361  template<typename _CharT> struct __formatter_chrono;
4362 
4363 } // namespace __format
4364 /// @endcond
4365 
4366  /** Context for std::format and similar functions.
4367  *
4368  * A formatting context contains an output iterator and locale to use
4369  * for the formatting operations. Most programs will never need to use
4370  * this class template explicitly. For typical uses of `std::format` the
4371  * library will use the specializations `std::format_context` (for `char`)
4372  * and `std::wformat_context` (for `wchar_t`).
4373  *
4374  * You are not allowed to define partial or explicit specializations of
4375  * this class template.
4376  *
4377  * @since C++20
4378  */
4379  template<typename _Out, typename _CharT>
4380  class basic_format_context
4381  {
4382  static_assert( output_iterator<_Out, const _CharT&> );
4383 
4384  basic_format_args<basic_format_context> _M_args;
4385  _Out _M_out;
4386  __format::_Optional_locale _M_loc;
4387 
4388  basic_format_context(basic_format_args<basic_format_context> __args,
4389  _Out __out)
4390  : _M_args(__args), _M_out(std::move(__out))
4391  { }
4392 
4393  basic_format_context(basic_format_args<basic_format_context> __args,
4394  _Out __out, const std::locale& __loc)
4395  : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
4396  { }
4397 
4398  // _GLIBCXX_RESOLVE_LIB_DEFECTS
4399  // 4061. Should std::basic_format_context be
4400  // default-constructible/copyable/movable?
4401  basic_format_context(const basic_format_context&) = delete;
4402  basic_format_context& operator=(const basic_format_context&) = delete;
4403 
4404  template<typename _Out2, typename _CharT2, typename _Context2>
4405  friend _Out2
4406  __format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
4407  const basic_format_args<_Context2>&,
4408  const locale*);
4409 
4410  friend __format::__formatter_chrono<_CharT>;
4411 
4412  public:
4413  ~basic_format_context() = default;
4414 
4415  using iterator = _Out;
4416  using char_type = _CharT;
4417  template<typename _Tp>
4418  using formatter_type = formatter<_Tp, _CharT>;
4419 
4420  [[nodiscard]]
4421  basic_format_arg<basic_format_context>
4422  arg(size_t __id) const noexcept
4423  { return _M_args.get(__id); }
4424 
4425  [[nodiscard]]
4426  std::locale locale() { return _M_loc.value(); }
4427 
4428  [[nodiscard]]
4429  iterator out() { return std::move(_M_out); }
4430 
4431  void advance_to(iterator __it) { _M_out = std::move(__it); }
4432  };
4433 
4434 
4435 /// @cond undocumented
4436 namespace __format
4437 {
4438  // Abstract base class defining an interface for scanning format strings.
4439  // Scan the characters in a format string, dividing it up into strings of
4440  // ordinary characters, escape sequences, and replacement fields.
4441  // Call virtual functions for derived classes to parse format-specifiers
4442  // or write formatted output.
4443  template<typename _CharT>
4444  struct _Scanner
4445  {
4446  using iterator = typename basic_format_parse_context<_CharT>::iterator;
4447 
4448  struct _Parse_context : basic_format_parse_context<_CharT>
4449  {
4450  using basic_format_parse_context<_CharT>::basic_format_parse_context;
4451  const _Arg_t* _M_types = nullptr;
4452  } _M_pc;
4453 
4454  constexpr explicit
4455  _Scanner(basic_string_view<_CharT> __str, size_t __nargs = (size_t)-1)
4456  : _M_pc(__str, __nargs)
4457  { }
4458 
4459  constexpr iterator begin() const noexcept { return _M_pc.begin(); }
4460  constexpr iterator end() const noexcept { return _M_pc.end(); }
4461 
4462  constexpr void
4463  _M_scan()
4464  {
4465  basic_string_view<_CharT> __fmt = _M_fmt_str();
4466 
4467  if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
4468  {
4469  _M_pc.advance_to(begin() + 1);
4470  _M_format_arg(_M_pc.next_arg_id());
4471  return;
4472  }
4473 
4474  size_t __lbr = __fmt.find('{');
4475  size_t __rbr = __fmt.find('}');
4476 
4477  while (__fmt.size())
4478  {
4479  auto __cmp = __lbr <=> __rbr;
4480  if (__cmp == 0)
4481  {
4482  _M_on_chars(end());
4483  _M_pc.advance_to(end());
4484  return;
4485  }
4486  else if (__cmp < 0)
4487  {
4488  if (__lbr + 1 == __fmt.size()
4489  || (__rbr == __fmt.npos && __fmt[__lbr + 1] != '{'))
4490  __format::__unmatched_left_brace_in_format_string();
4491  const bool __is_escape = __fmt[__lbr + 1] == '{';
4492  iterator __last = begin() + __lbr + int(__is_escape);
4493  _M_on_chars(__last);
4494  _M_pc.advance_to(__last + 1);
4495  __fmt = _M_fmt_str();
4496  if (__is_escape)
4497  {
4498  if (__rbr != __fmt.npos)
4499  __rbr -= __lbr + 2;
4500  __lbr = __fmt.find('{');
4501  }
4502  else
4503  {
4504  _M_on_replacement_field();
4505  __fmt = _M_fmt_str();
4506  __lbr = __fmt.find('{');
4507  __rbr = __fmt.find('}');
4508  }
4509  }
4510  else
4511  {
4512  if (++__rbr == __fmt.size() || __fmt[__rbr] != '}')
4513  __format::__unmatched_right_brace_in_format_string();
4514  iterator __last = begin() + __rbr;
4515  _M_on_chars(__last);
4516  _M_pc.advance_to(__last + 1);
4517  __fmt = _M_fmt_str();
4518  if (__lbr != __fmt.npos)
4519  __lbr -= __rbr + 1;
4520  __rbr = __fmt.find('}');
4521  }
4522  }
4523  }
4524 
4525  constexpr basic_string_view<_CharT>
4526  _M_fmt_str() const noexcept
4527  { return {begin(), end()}; }
4528 
4529  constexpr virtual void _M_on_chars(iterator) { }
4530 
4531  constexpr void _M_on_replacement_field()
4532  {
4533  auto __next = begin();
4534 
4535  size_t __id;
4536  if (*__next == '}')
4537  __id = _M_pc.next_arg_id();
4538  else if (*__next == ':')
4539  {
4540  __id = _M_pc.next_arg_id();
4541  _M_pc.advance_to(++__next);
4542  }
4543  else
4544  {
4545  auto [__i, __ptr] = __format::__parse_arg_id(begin(), end());
4546  if (!__ptr || !(*__ptr == '}' || *__ptr == ':'))
4547  __format::__invalid_arg_id_in_format_string();
4548  _M_pc.check_arg_id(__id = __i);
4549  if (*__ptr == ':')
4550  {
4551  _M_pc.advance_to(++__ptr);
4552  }
4553  else
4554  _M_pc.advance_to(__ptr);
4555  }
4556  _M_format_arg(__id);
4557  if (begin() == end() || *begin() != '}')
4558  __format::__unmatched_left_brace_in_format_string();
4559  _M_pc.advance_to(begin() + 1); // Move past '}'
4560  }
4561 
4562  constexpr virtual void _M_format_arg(size_t __id) = 0;
4563  };
4564 
4565  // Process a format string and format the arguments in the context.
4566  template<typename _Out, typename _CharT>
4567  class _Formatting_scanner : public _Scanner<_CharT>
4568  {
4569  public:
4570  _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
4571  basic_string_view<_CharT> __str)
4572  : _Scanner<_CharT>(__str), _M_fc(__fc)
4573  { }
4574 
4575  private:
4576  basic_format_context<_Out, _CharT>& _M_fc;
4577 
4578  using iterator = typename _Scanner<_CharT>::iterator;
4579 
4580  constexpr void
4581  _M_on_chars(iterator __last) override
4582  {
4583  basic_string_view<_CharT> __str(this->begin(), __last);
4584  _M_fc.advance_to(__format::__write(_M_fc.out(), __str));
4585  }
4586 
4587  constexpr void
4588  _M_format_arg(size_t __id) override
4589  {
4590  using _Context = basic_format_context<_Out, _CharT>;
4591  using handle = typename basic_format_arg<_Context>::handle;
4592 
4593  __format::__visit_format_arg([this](auto& __arg) {
4594  using _Type = remove_reference_t<decltype(__arg)>;
4595  using _Formatter = typename _Context::template formatter_type<_Type>;
4596  if constexpr (is_same_v<_Type, monostate>)
4597  __format::__invalid_arg_id_in_format_string();
4598  else if constexpr (is_same_v<_Type, handle>)
4599  __arg.format(this->_M_pc, this->_M_fc);
4600  else if constexpr (is_default_constructible_v<_Formatter>)
4601  {
4602  _Formatter __f;
4603  this->_M_pc.advance_to(__f.parse(this->_M_pc));
4604  this->_M_fc.advance_to(__f.format(__arg, this->_M_fc));
4605  }
4606  else
4607  static_assert(__format::__formattable_with<_Type, _Context>);
4608  }, _M_fc.arg(__id));
4609  }
4610  };
4611 
4612  template<typename _CharT, typename _Tp>
4613  consteval _Arg_t
4614  __to_arg_t_enum() noexcept
4615  {
4616  using _Context = __format::__format_context<_CharT>;
4617  using _Fmt_arg = basic_format_arg<_Context>;
4618  using _NormalizedTp = typename _Fmt_arg::template _Normalize<_Tp>;
4619  return _Fmt_arg::template _S_to_enum<_NormalizedTp>();
4620  }
4621 
4622  // Validate a format string for Args.
4623  template<typename _CharT, typename... _Args>
4624  class _Checking_scanner : public _Scanner<_CharT>
4625  {
4626  static_assert(
4627  (is_default_constructible_v<formatter<_Args, _CharT>> && ...),
4628  "std::formatter must be specialized for each type being formatted");
4629 
4630  public:
4631  consteval
4632  _Checking_scanner(basic_string_view<_CharT> __str)
4633  : _Scanner<_CharT>(__str, sizeof...(_Args))
4634  {
4635 #if __cpp_lib_format >= 202305L
4636  this->_M_pc._M_types = _M_types.data();
4637 #endif
4638  }
4639 
4640  private:
4641  constexpr void
4642  _M_format_arg(size_t __id) override
4643  {
4644  if constexpr (sizeof...(_Args) != 0)
4645  {
4646  if (__id < sizeof...(_Args))
4647  {
4648  _M_parse_format_spec<_Args...>(__id);
4649  return;
4650  }
4651  }
4652  __builtin_unreachable();
4653  }
4654 
4655  template<typename _Tp, typename... _OtherArgs>
4656  constexpr void
4657  _M_parse_format_spec(size_t __id)
4658  {
4659  if (__id == 0)
4660  {
4661  formatter<_Tp, _CharT> __f;
4662  this->_M_pc.advance_to(__f.parse(this->_M_pc));
4663  }
4664  else if constexpr (sizeof...(_OtherArgs) != 0)
4665  _M_parse_format_spec<_OtherArgs...>(__id - 1);
4666  else
4667  __builtin_unreachable();
4668  }
4669 
4670 #if __cpp_lib_format >= 202305L
4671  array<_Arg_t, sizeof...(_Args)>
4672  _M_types{ { __format::__to_arg_t_enum<_CharT, _Args>()... } };
4673 #endif
4674  };
4675 
4676  template<typename _Out, typename _CharT, typename _Context>
4677  inline _Out
4678  __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
4679  const basic_format_args<_Context>& __args,
4680  const locale* __loc)
4681  {
4682  _Iter_sink<_CharT, _Out> __sink(std::move(__out));
4683  _Sink_iter<_CharT> __sink_out;
4684 
4685  if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
4686  __sink_out = __out; // Already a sink iterator, safe to use post-move.
4687  else
4688  __sink_out = __sink.out();
4689 
4690  if constexpr (is_same_v<_CharT, char>)
4691  // Fast path for "{}" format strings and simple format arg types.
4692  if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
4693  {
4694  bool __done = false;
4695  __format::__visit_format_arg([&](auto& __arg) {
4696  using _Tp = remove_cvref_t<decltype(__arg)>;
4697  if constexpr (is_same_v<_Tp, bool>)
4698  {
4699  size_t __len = 4 + !__arg;
4700  const char* __chars[] = { "false", "true" };
4701  if (auto __res = __sink_out._M_reserve(__len))
4702  {
4703  __builtin_memcpy(__res.get(), __chars[__arg], __len);
4704  __res._M_bump(__len);
4705  __done = true;
4706  }
4707  }
4708  else if constexpr (is_same_v<_Tp, char>)
4709  {
4710  if (auto __res = __sink_out._M_reserve(1))
4711  {
4712  *__res.get() = __arg;
4713  __res._M_bump(1);
4714  __done = true;
4715  }
4716  }
4717  else if constexpr (is_integral_v<_Tp>)
4718  {
4719  make_unsigned_t<_Tp> __uval;
4720  const bool __neg = __arg < 0;
4721  if (__neg)
4722  __uval = make_unsigned_t<_Tp>(~__arg) + 1u;
4723  else
4724  __uval = __arg;
4725  const auto __n = __detail::__to_chars_len(__uval);
4726  if (auto __res = __sink_out._M_reserve(__n + __neg))
4727  {
4728  auto __ptr = __res.get();
4729  *__ptr = '-';
4730  __detail::__to_chars_10_impl(__ptr + (int)__neg, __n,
4731  __uval);
4732  __res._M_bump(__n + __neg);
4733  __done = true;
4734  }
4735  }
4736  else if constexpr (is_convertible_v<_Tp, string_view>)
4737  {
4738  string_view __sv = __arg;
4739  if (auto __res = __sink_out._M_reserve(__sv.size()))
4740  {
4741  __builtin_memcpy(__res.get(), __sv.data(), __sv.size());
4742  __res._M_bump(__sv.size());
4743  __done = true;
4744  }
4745  }
4746  }, __args.get(0));
4747 
4748  if (__done)
4749  {
4750  if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
4751  return __sink_out;
4752  else
4753  return std::move(__sink)._M_finish().out;
4754  }
4755  }
4756 
4757  auto __ctx = __loc == nullptr
4758  ? _Context(__args, __sink_out)
4759  : _Context(__args, __sink_out, *__loc);
4760  _Formatting_scanner<_Sink_iter<_CharT>, _CharT> __scanner(__ctx, __fmt);
4761  __scanner._M_scan();
4762 
4763  if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
4764  return __ctx.out();
4765  else
4766  return std::move(__sink)._M_finish().out;
4767  }
4768 #pragma GCC diagnostic pop
4769 
4770 } // namespace __format
4771 /// @endcond
4772 
4773 #if __cpp_lib_format >= 202305L // >= C++26
4774  /// @cond undocumented
4775  // Common implementation of check_dynamic_spec{,_string,_integral}
4776  template<typename _CharT>
4777  template<typename... _Ts>
4778  consteval void
4779  basic_format_parse_context<_CharT>::
4780  __check_dynamic_spec(size_t __id) noexcept
4781  {
4782  if (__id >= _M_num_args)
4783  __format::__invalid_arg_id_in_format_string();
4784  if constexpr (sizeof...(_Ts) != 0)
4785  {
4786  using _Parse_ctx = __format::_Scanner<_CharT>::_Parse_context;
4787  auto __arg = static_cast<_Parse_ctx*>(this)->_M_types[__id];
4788  __format::_Arg_t __types[] = {
4789  __format::__to_arg_t_enum<_CharT, _Ts>()...
4790  };
4791  for (auto __t : __types)
4792  if (__arg == __t)
4793  return;
4794  }
4795  __invalid_dynamic_spec("arg(id) type does not match");
4796  }
4797  /// @endcond
4798 #endif
4799 
4800  template<typename _CharT, typename... _Args>
4801  template<typename _Tp>
4802  requires convertible_to<const _Tp&, basic_string_view<_CharT>>
4803  consteval
4804  basic_format_string<_CharT, _Args...>::
4805  basic_format_string(const _Tp& __s)
4806  : _M_str(__s)
4807  {
4808  __format::_Checking_scanner<_CharT, remove_cvref_t<_Args>...>
4809  __scanner(_M_str);
4810  __scanner._M_scan();
4811  }
4812 
4813  // [format.functions], formatting functions
4814 
4815  template<typename _Out> requires output_iterator<_Out, const char&>
4816  [[__gnu__::__always_inline__]]
4817  inline _Out
4818  vformat_to(_Out __out, string_view __fmt, format_args __args)
4819  { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
4820 
4821 #ifdef _GLIBCXX_USE_WCHAR_T
4822  template<typename _Out> requires output_iterator<_Out, const wchar_t&>
4823  [[__gnu__::__always_inline__]]
4824  inline _Out
4825  vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
4826  { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
4827 #endif
4828 
4829  template<typename _Out> requires output_iterator<_Out, const char&>
4830  [[__gnu__::__always_inline__]]
4831  inline _Out
4832  vformat_to(_Out __out, const locale& __loc, string_view __fmt,
4833  format_args __args)
4834  {
4835  return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
4836  }
4837 
4838 #ifdef _GLIBCXX_USE_WCHAR_T
4839  template<typename _Out> requires output_iterator<_Out, const wchar_t&>
4840  [[__gnu__::__always_inline__]]
4841  inline _Out
4842  vformat_to(_Out __out, const locale& __loc, wstring_view __fmt,
4843  wformat_args __args)
4844  {
4845  return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
4846  }
4847 #endif
4848 
4849  [[nodiscard]]
4850  inline string
4851  vformat(string_view __fmt, format_args __args)
4852  {
4853  __format::_Str_sink<char> __buf;
4854  std::vformat_to(__buf.out(), __fmt, __args);
4855  return std::move(__buf).get();
4856  }
4857 
4858 #ifdef _GLIBCXX_USE_WCHAR_T
4859  [[nodiscard]]
4860  inline wstring
4861  vformat(wstring_view __fmt, wformat_args __args)
4862  {
4863  __format::_Str_sink<wchar_t> __buf;
4864  std::vformat_to(__buf.out(), __fmt, __args);
4865  return std::move(__buf).get();
4866  }
4867 #endif
4868 
4869  [[nodiscard]]
4870  inline string
4871  vformat(const locale& __loc, string_view __fmt, format_args __args)
4872  {
4873  __format::_Str_sink<char> __buf;
4874  std::vformat_to(__buf.out(), __loc, __fmt, __args);
4875  return std::move(__buf).get();
4876  }
4877 
4878 #ifdef _GLIBCXX_USE_WCHAR_T
4879  [[nodiscard]]
4880  inline wstring
4881  vformat(const locale& __loc, wstring_view __fmt, wformat_args __args)
4882  {
4883  __format::_Str_sink<wchar_t> __buf;
4884  std::vformat_to(__buf.out(), __loc, __fmt, __args);
4885  return std::move(__buf).get();
4886  }
4887 #endif
4888 
4889  template<typename... _Args>
4890  [[nodiscard]]
4891  inline string
4892  format(format_string<_Args...> __fmt, _Args&&... __args)
4893  { return std::vformat(__fmt.get(), std::make_format_args(__args...)); }
4894 
4895 #ifdef _GLIBCXX_USE_WCHAR_T
4896  template<typename... _Args>
4897  [[nodiscard]]
4898  inline wstring
4899  format(wformat_string<_Args...> __fmt, _Args&&... __args)
4900  { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); }
4901 #endif
4902 
4903  template<typename... _Args>
4904  [[nodiscard]]
4905  inline string
4906  format(const locale& __loc, format_string<_Args...> __fmt,
4907  _Args&&... __args)
4908  {
4909  return std::vformat(__loc, __fmt.get(),
4910  std::make_format_args(__args...));
4911  }
4912 
4913 #ifdef _GLIBCXX_USE_WCHAR_T
4914  template<typename... _Args>
4915  [[nodiscard]]
4916  inline wstring
4917  format(const locale& __loc, wformat_string<_Args...> __fmt,
4918  _Args&&... __args)
4919  {
4920  return std::vformat(__loc, __fmt.get(),
4921  std::make_wformat_args(__args...));
4922  }
4923 #endif
4924 
4925  template<typename _Out, typename... _Args>
4926  requires output_iterator<_Out, const char&>
4927  inline _Out
4928  format_to(_Out __out, format_string<_Args...> __fmt, _Args&&... __args)
4929  {
4930  return std::vformat_to(std::move(__out), __fmt.get(),
4931  std::make_format_args(__args...));
4932  }
4933 
4934 #ifdef _GLIBCXX_USE_WCHAR_T
4935  template<typename _Out, typename... _Args>
4936  requires output_iterator<_Out, const wchar_t&>
4937  inline _Out
4938  format_to(_Out __out, wformat_string<_Args...> __fmt, _Args&&... __args)
4939  {
4940  return std::vformat_to(std::move(__out), __fmt.get(),
4941  std::make_wformat_args(__args...));
4942  }
4943 #endif
4944 
4945  template<typename _Out, typename... _Args>
4946  requires output_iterator<_Out, const char&>
4947  inline _Out
4948  format_to(_Out __out, const locale& __loc, format_string<_Args...> __fmt,
4949  _Args&&... __args)
4950  {
4951  return std::vformat_to(std::move(__out), __loc, __fmt.get(),
4952  std::make_format_args(__args...));
4953  }
4954 
4955 #ifdef _GLIBCXX_USE_WCHAR_T
4956  template<typename _Out, typename... _Args>
4957  requires output_iterator<_Out, const wchar_t&>
4958  inline _Out
4959  format_to(_Out __out, const locale& __loc, wformat_string<_Args...> __fmt,
4960  _Args&&... __args)
4961  {
4962  return std::vformat_to(std::move(__out), __loc, __fmt.get(),
4963  std::make_wformat_args(__args...));
4964  }
4965 #endif
4966 
4967  template<typename _Out, typename... _Args>
4968  requires output_iterator<_Out, const char&>
4969  inline format_to_n_result<_Out>
4970  format_to_n(_Out __out, iter_difference_t<_Out> __n,
4971  format_string<_Args...> __fmt, _Args&&... __args)
4972  {
4973  __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
4974  std::vformat_to(__sink.out(), __fmt.get(),
4975  std::make_format_args(__args...));
4976  return std::move(__sink)._M_finish();
4977  }
4978 
4979 #ifdef _GLIBCXX_USE_WCHAR_T
4980  template<typename _Out, typename... _Args>
4981  requires output_iterator<_Out, const wchar_t&>
4982  inline format_to_n_result<_Out>
4983  format_to_n(_Out __out, iter_difference_t<_Out> __n,
4984  wformat_string<_Args...> __fmt, _Args&&... __args)
4985  {
4986  __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
4987  std::vformat_to(__sink.out(), __fmt.get(),
4988  std::make_wformat_args(__args...));
4989  return std::move(__sink)._M_finish();
4990  }
4991 #endif
4992 
4993  template<typename _Out, typename... _Args>
4994  requires output_iterator<_Out, const char&>
4995  inline format_to_n_result<_Out>
4996  format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
4997  format_string<_Args...> __fmt, _Args&&... __args)
4998  {
4999  __format::_Iter_sink<char, _Out> __sink(std::move(__out), __n);
5000  std::vformat_to(__sink.out(), __loc, __fmt.get(),
5001  std::make_format_args(__args...));
5002  return std::move(__sink)._M_finish();
5003  }
5004 
5005 #ifdef _GLIBCXX_USE_WCHAR_T
5006  template<typename _Out, typename... _Args>
5007  requires output_iterator<_Out, const wchar_t&>
5008  inline format_to_n_result<_Out>
5009  format_to_n(_Out __out, iter_difference_t<_Out> __n, const locale& __loc,
5010  wformat_string<_Args...> __fmt, _Args&&... __args)
5011  {
5012  __format::_Iter_sink<wchar_t, _Out> __sink(std::move(__out), __n);
5013  std::vformat_to(__sink.out(), __loc, __fmt.get(),
5014  std::make_wformat_args(__args...));
5015  return std::move(__sink)._M_finish();
5016  }
5017 #endif
5018 
5019 /// @cond undocumented
5020 namespace __format
5021 {
5022 #if 1
5023  template<typename _CharT>
5024  class _Counting_sink final : public _Iter_sink<_CharT, _CharT*>
5025  {
5026  public:
5027  _Counting_sink() : _Iter_sink<_CharT, _CharT*>(nullptr, 0) { }
5028 
5029  [[__gnu__::__always_inline__]]
5030  size_t
5031  count() const
5032  { return this->_M_count + this->_M_used().size(); }
5033  };
5034 #else
5035  template<typename _CharT>
5036  class _Counting_sink : public _Buf_sink<_CharT>
5037  {
5038  size_t _M_count = 0;
5039 
5040  void
5041  _M_overflow() override
5042  {
5043  if (!std::is_constant_evaluated())
5044  _M_count += this->_M_used().size();
5045  this->_M_rewind();
5046  }
5047 
5048  public:
5049  _Counting_sink() = default;
5050 
5051  [[__gnu__::__always_inline__]]
5052  size_t
5053  count() noexcept
5054  {
5055  _Counting_sink::_M_overflow();
5056  return _M_count;
5057  }
5058  };
5059 #endif
5060 } // namespace __format
5061 /// @endcond
5062 
5063  template<typename... _Args>
5064  [[nodiscard]]
5065  inline size_t
5066  formatted_size(format_string<_Args...> __fmt, _Args&&... __args)
5067  {
5068  __format::_Counting_sink<char> __buf;
5069  std::vformat_to(__buf.out(), __fmt.get(),
5070  std::make_format_args(__args...));
5071  return __buf.count();
5072  }
5073 
5074 #ifdef _GLIBCXX_USE_WCHAR_T
5075  template<typename... _Args>
5076  [[nodiscard]]
5077  inline size_t
5078  formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args)
5079  {
5080  __format::_Counting_sink<wchar_t> __buf;
5081  std::vformat_to(__buf.out(), __fmt.get(),
5082  std::make_wformat_args(__args...));
5083  return __buf.count();
5084  }
5085 #endif
5086 
5087  template<typename... _Args>
5088  [[nodiscard]]
5089  inline size_t
5090  formatted_size(const locale& __loc, format_string<_Args...> __fmt,
5091  _Args&&... __args)
5092  {
5093  __format::_Counting_sink<char> __buf;
5094  std::vformat_to(__buf.out(), __loc, __fmt.get(),
5095  std::make_format_args(__args...));
5096  return __buf.count();
5097  }
5098 
5099 #ifdef _GLIBCXX_USE_WCHAR_T
5100  template<typename... _Args>
5101  [[nodiscard]]
5102  inline size_t
5103  formatted_size(const locale& __loc, wformat_string<_Args...> __fmt,
5104  _Args&&... __args)
5105  {
5106  __format::_Counting_sink<wchar_t> __buf;
5107  std::vformat_to(__buf.out(), __loc, __fmt.get(),
5108  std::make_wformat_args(__args...));
5109  return __buf.count();
5110  }
5111 #endif
5112 
5113 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
5114  // [format.range], formatting of ranges
5115  // [format.range.fmtkind], variable template format_kind
5116  enum class range_format {
5117  disabled,
5118  map,
5119  set,
5120  sequence,
5121  string,
5122  debug_string
5123  };
5124 
5125  /** @brief A constant determining how a range should be formatted.
5126  *
5127  * The primary template of `std::format_kind` cannot be instantiated.
5128  * There is a partial specialization for input ranges and you can
5129  * specialize the variable template for your own cv-unqualified types
5130  * that satisfy the `ranges::input_range` concept.
5131  *
5132  * @since C++23
5133  */
5134  template<typename _Rg>
5135  constexpr auto format_kind = []{
5136  static_assert(false, "cannot use primary template of 'std::format_kind'");
5137  return type_identity<_Rg>{};
5138  }();
5139 
5140  /// @cond undocumented
5141  template<typename _Tp>
5142  consteval range_format
5143  __fmt_kind()
5144  {
5145  using _Ref = ranges::range_reference_t<_Tp>;
5146  if constexpr (is_same_v<remove_cvref_t<_Ref>, _Tp>)
5147  return range_format::disabled;
5148  else if constexpr (requires { typename _Tp::key_type; })
5149  {
5150  if constexpr (requires { typename _Tp::mapped_type; })
5151  {
5152  using _Up = remove_cvref_t<_Ref>;
5153  if constexpr (__is_pair<_Up>)
5154  return range_format::map;
5155  else if constexpr (__is_specialization_of<_Up, tuple>)
5156  if constexpr (tuple_size_v<_Up> == 2)
5157  return range_format::map;
5158  }
5159  return range_format::set;
5160  }
5161  else
5162  return range_format::sequence;
5163  }
5164  /// @endcond
5165 
5166  /// A constant determining how a range should be formatted.
5167  template<ranges::input_range _Rg> requires same_as<_Rg, remove_cvref_t<_Rg>>
5168  constexpr range_format format_kind<_Rg> = __fmt_kind<_Rg>();
5169 
5170 /// @cond undocumented
5171 namespace __format
5172 {
5173  template<typename _CharT, typename _Out, typename _Callback>
5174  typename basic_format_context<_Out, _CharT>::iterator
5175  __format_padded(basic_format_context<_Out, _CharT>& __fc,
5176  const _Spec<_CharT>& __spec,
5177  _Callback&& __call)
5178  {
5179  // This is required to implement formatting with padding,
5180  // as we need to format to temporary buffer, using the same iterator.
5181  static_assert(is_same_v<_Out, __format::_Sink_iter<_CharT>>);
5182 
5183  if (__spec._M_get_width(__fc) == 0)
5184  return __call(__fc);
5185 
5186  struct _Restore_out
5187  {
5188  _Restore_out(basic_format_context<_Sink_iter<_CharT>, _CharT>& __fc)
5189  : _M_ctx(std::addressof(__fc)), _M_out(__fc.out())
5190  { }
5191 
5192  void _M_trigger()
5193  {
5194  if (_M_ctx)
5195  _M_ctx->advance_to(_M_out);
5196  _M_ctx = nullptr;
5197  }
5198 
5199  ~_Restore_out()
5200  { _M_trigger(); }
5201 
5202  private:
5203  basic_format_context<_Sink_iter<_CharT>, _CharT>* _M_ctx;
5204  _Sink_iter<_CharT> _M_out;
5205  };
5206 
5207  _Restore_out __restore(__fc);
5208  // TODO Consider double sinking, first buffer of width
5209  // size and then original sink, if first buffer is overun
5210  // we do not need to align
5211  _Str_sink<_CharT> __buf;
5212  __fc.advance_to(__buf.out());
5213  __call(__fc);
5214  __restore._M_trigger();
5215 
5216  basic_string_view<_CharT> __str(__buf.view());
5217  size_t __width;
5218  if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
5219  __width = __unicode::__field_width(__str);
5220  else
5221  __width = __str.size();
5222 
5223  return __format::__write_padded_as_spec(__str, __width, __fc, __spec);
5224  }
5225 
5226  // _Rg& and const _Rg& are both formattable and use same formatter
5227  // specialization for their references.
5228  template<typename _Rg, typename _CharT>
5229  concept __simply_formattable_range
5230  = __const_formattable_range<_Rg, _CharT>
5231  && same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>,
5232  remove_cvref_t<ranges::range_reference_t<const _Rg>>>;
5233 
5234  template<size_t _Pos, typename _Tp, typename _CharT>
5235  struct __indexed_formatter_storage
5236  {
5237  constexpr void
5238  _M_parse()
5239  {
5240  basic_format_parse_context<_CharT> __pc({});
5241  if (_M_formatter.parse(__pc) != __pc.end())
5242  __format::__failed_to_parse_format_spec();
5243  }
5244 
5245  template<typename _Out>
5246  void
5247  _M_format(__maybe_const<_Tp, _CharT>& __elem,
5248  basic_format_context<_Out, _CharT>& __fc,
5249  basic_string_view<_CharT> __sep) const
5250  {
5251  if constexpr (_Pos != 0)
5252  __fc.advance_to(__format::__write(__fc.out(), __sep));
5253  __fc.advance_to(_M_formatter.format(__elem, __fc));
5254  }
5255 
5256  [[__gnu__::__always_inline__]]
5257  constexpr void
5258  set_debug_format()
5259  {
5260  if constexpr (__has_debug_format<formatter<_Tp, _CharT>>)
5261  _M_formatter.set_debug_format();
5262  }
5263 
5264  private:
5265  formatter<_Tp, _CharT> _M_formatter;
5266  };
5267 
5268  template<typename _CharT, typename... _Tps>
5269  class __tuple_formatter
5270  {
5271  using _String_view = basic_string_view<_CharT>;
5272  using _Seps = __format::_Separators<_CharT>;
5273 
5274  public:
5275  constexpr void
5276  set_separator(basic_string_view<_CharT> __sep) noexcept
5277  { _M_sep = __sep; }
5278 
5279  constexpr void
5280  set_brackets(basic_string_view<_CharT> __open,
5281  basic_string_view<_CharT> __close) noexcept
5282  {
5283  _M_open = __open;
5284  _M_close = __close;
5285  }
5286 
5287  // We deviate from standard, that declares this as template accepting
5288  // unconstrained ParseContext type, which seems unimplementable.
5289  constexpr typename basic_format_parse_context<_CharT>::iterator
5290  parse(basic_format_parse_context<_CharT>& __pc)
5291  {
5292  auto __first = __pc.begin();
5293  const auto __last = __pc.end();
5294  __format::_Spec<_CharT> __spec{};
5295 
5296  auto __finished = [&]
5297  {
5298  if (__first != __last && *__first != '}')
5299  return false;
5300 
5301  _M_spec = __spec;
5302  _M_felems._M_parse();
5303  _M_felems.set_debug_format();
5304  return true;
5305  };
5306 
5307  if (__finished())
5308  return __first;
5309 
5310  __first = __spec._M_parse_fill_and_align(__first, __last, "{:");
5311  if (__finished())
5312  return __first;
5313 
5314  __first = __spec._M_parse_width(__first, __last, __pc);
5315  if (__finished())
5316  return __first;
5317 
5318  if (*__first == 'n')
5319  {
5320  ++__first;
5321  _M_open = _M_close = _String_view();
5322  }
5323  else if (*__first == 'm')
5324  {
5325  ++__first;
5326  if constexpr (sizeof...(_Tps) == 2)
5327  {
5328  _M_sep = _Seps::_S_colon();
5329  _M_open = _M_close = _String_view();
5330  }
5331  else
5332  __throw_format_error("format error: 'm' specifier requires range"
5333  " of pair or tuple of two elements");
5334  }
5335 
5336  if (__finished())
5337  return __first;
5338 
5339  __format::__failed_to_parse_format_spec();
5340  }
5341 
5342  protected:
5343  template<typename _Tuple, typename _Out, size_t... _Ids>
5344  typename basic_format_context<_Out, _CharT>::iterator
5345  _M_format(_Tuple& __tuple, index_sequence<_Ids...>,
5346  basic_format_context<_Out, _CharT>& __fc) const
5347  { return _M_format_elems(std::get<_Ids>(__tuple)..., __fc); }
5348 
5349  template<typename _Out>
5350  typename basic_format_context<_Out, _CharT>::iterator
5351  _M_format_elems(__maybe_const<_Tps, _CharT>&... __elems,
5352  basic_format_context<_Out, _CharT>& __fc) const
5353  {
5354  return __format::__format_padded(
5355  __fc, _M_spec,
5356  [this, &__elems...](basic_format_context<_Out, _CharT>& __nfc)
5357  {
5358  __nfc.advance_to(__format::__write(__nfc.out(), _M_open));
5359  _M_felems._M_format(__elems..., __nfc, _M_sep);
5360  return __format::__write(__nfc.out(), _M_close);
5361  });
5362  }
5363 
5364  private:
5365  template<size_t... _Ids>
5366  struct __formatters_storage
5367  : __indexed_formatter_storage<_Ids, _Tps, _CharT>...
5368  {
5369  template<size_t _Id, typename _Up>
5370  using _Base = __indexed_formatter_storage<_Id, _Up, _CharT>;
5371 
5372  constexpr void
5373  _M_parse()
5374  {
5375  (_Base<_Ids, _Tps>::_M_parse(), ...);
5376  }
5377 
5378  template<typename _Out>
5379  void
5380  _M_format(__maybe_const<_Tps, _CharT>&... __elems,
5381  basic_format_context<_Out, _CharT>& __fc,
5382  _String_view __sep) const
5383  {
5384  (_Base<_Ids, _Tps>::_M_format(__elems, __fc, __sep), ...);
5385  }
5386 
5387  constexpr void
5388  set_debug_format()
5389  {
5390  (_Base<_Ids, _Tps>::set_debug_format(), ...);
5391  }
5392  };
5393 
5394  template<size_t... _Ids>
5395  static auto
5396  _S_create_storage(index_sequence<_Ids...>)
5397  -> __formatters_storage<_Ids...>;
5398  using _Formatters
5399  = decltype(_S_create_storage(index_sequence_for<_Tps...>()));
5400 
5401  _Spec<_CharT> _M_spec{};
5402  _String_view _M_open = _Seps::_S_parens().substr(0, 1);
5403  _String_view _M_close = _Seps::_S_parens().substr(1, 1);
5404  _String_view _M_sep = _Seps::_S_comma();
5405  _Formatters _M_felems;
5406  };
5407 
5408  template<typename _Tp>
5409  concept __is_map_formattable
5410  = __is_pair<_Tp> || (__is_tuple_v<_Tp> && tuple_size_v<_Tp> == 2);
5411 
5412 } // namespace __format
5413 /// @endcond
5414 
5415  // [format.tuple] Tuple formatter
5416  template<__format::__char _CharT, formattable<_CharT> _Fp,
5417  formattable<_CharT> _Sp>
5418  struct formatter<pair<_Fp, _Sp>, _CharT>
5419  : __format::__tuple_formatter<_CharT, remove_cvref_t<_Fp>,
5420  remove_cvref_t<_Sp>>
5421  {
5422  private:
5423  using __maybe_const_pair
5424  = __conditional_t<formattable<const _Fp, _CharT>
5425  && formattable<const _Sp, _CharT>,
5426  const pair<_Fp, _Sp>, pair<_Fp, _Sp>>;
5427  public:
5428  // We deviate from standard, that declares this as template accepting
5429  // unconstrained FormatContext type, which seems unimplementable.
5430  template<typename _Out>
5431  typename basic_format_context<_Out, _CharT>::iterator
5432  format(__maybe_const_pair& __p,
5433  basic_format_context<_Out, _CharT>& __fc) const
5434  { return this->_M_format_elems(__p.first, __p.second, __fc); }
5435  };
5436 
5437  template<__format::__char _CharT, formattable<_CharT>... _Tps>
5438  struct formatter<tuple<_Tps...>, _CharT>
5439  : __format::__tuple_formatter<_CharT, remove_cvref_t<_Tps>...>
5440  {
5441  private:
5442  using __maybe_const_tuple
5443  = __conditional_t<(formattable<const _Tps, _CharT> && ...),
5444  const tuple<_Tps...>, tuple<_Tps...>>;
5445  public:
5446  // We deviate from standard, that declares this as template accepting
5447  // unconstrained FormatContext type, which seems unimplementable.
5448  template<typename _Out>
5449  typename basic_format_context<_Out, _CharT>::iterator
5450  format(__maybe_const_tuple& __t,
5451  basic_format_context<_Out, _CharT>& __fc) const
5452  { return this->_M_format(__t, index_sequence_for<_Tps...>(), __fc); }
5453  };
5454 
5455  // [format.range.formatter], class template range_formatter
5456  template<typename _Tp, __format::__char _CharT>
5457  requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT>
5458  class range_formatter
5459  {
5460  using _String_view = basic_string_view<_CharT>;
5461  using _Seps = __format::_Separators<_CharT>;
5462 
5463  public:
5464  constexpr void
5465  set_separator(basic_string_view<_CharT> __sep) noexcept
5466  { _M_sep = __sep; }
5467 
5468  constexpr void
5469  set_brackets(basic_string_view<_CharT> __open,
5470  basic_string_view<_CharT> __close) noexcept
5471  {
5472  _M_open = __open;
5473  _M_close = __close;
5474  }
5475 
5476  constexpr formatter<_Tp, _CharT>&
5477  underlying() noexcept
5478  { return _M_fval; }
5479 
5480  constexpr const formatter<_Tp, _CharT>&
5481  underlying() const noexcept
5482  { return _M_fval; }
5483 
5484  // We deviate from standard, that declares this as template accepting
5485  // unconstrained ParseContext type, which seems unimplementable.
5486  constexpr typename basic_format_parse_context<_CharT>::iterator
5487  parse(basic_format_parse_context<_CharT>& __pc)
5488  {
5489  auto __first = __pc.begin();
5490  const auto __last = __pc.end();
5491  __format::_Spec<_CharT> __spec{};
5492  bool __no_brace = false;
5493 
5494  auto __finished = [&]
5495  { return __first == __last || *__first == '}'; };
5496 
5497  auto __finalize = [&]
5498  {
5499  _M_spec = __spec;
5500  return __first;
5501  };
5502 
5503  auto __parse_val = [&](_String_view __nfs = _String_view())
5504  {
5505  basic_format_parse_context<_CharT> __npc(__nfs);
5506  if (_M_fval.parse(__npc) != __npc.end())
5507  __format::__failed_to_parse_format_spec();
5508  if constexpr (__format::__has_debug_format<formatter<_Tp, _CharT>>)
5509  _M_fval.set_debug_format();
5510  return __finalize();
5511  };
5512 
5513  if (__finished())
5514  return __parse_val();
5515 
5516  __first = __spec._M_parse_fill_and_align(__first, __last, "{:");
5517  if (__finished())
5518  return __parse_val();
5519 
5520  __first = __spec._M_parse_width(__first, __last, __pc);
5521  if (__finished())
5522  return __parse_val();
5523 
5524  if (*__first == '?')
5525  {
5526  ++__first;
5527  __spec._M_type = __format::_Pres_esc;
5528  if (__finished() || *__first != 's')
5529  __throw_format_error("format error: '?' is allowed only in"
5530  " combination with 's'");
5531  }
5532 
5533  if (*__first == 's')
5534  {
5535  ++__first;
5536  if constexpr (same_as<_Tp, _CharT>)
5537  {
5538  if (__spec._M_type != __format::_Pres_esc)
5539  __spec._M_type = __format::_Pres_str;
5540  if (__finished())
5541  return __finalize();
5542  __throw_format_error("format error: element format specifier"
5543  " cannot be provided when 's' specifier is used");
5544  }
5545  else
5546  __throw_format_error("format error: 's' specifier requires"
5547  " range of character types");
5548  }
5549 
5550  if (__finished())
5551  return __parse_val();
5552 
5553  if (*__first == 'n')
5554  {
5555  ++__first;
5556  _M_open = _M_close = _String_view();
5557  __no_brace = true;
5558  }
5559 
5560  if (__finished())
5561  return __parse_val();
5562 
5563  if (*__first == 'm')
5564  {
5565  _String_view __m(__first, 1);
5566  ++__first;
5567  if constexpr (__format::__is_map_formattable<_Tp>)
5568  {
5569  _M_sep = _Seps::_S_comma();
5570  if (!__no_brace)
5571  {
5572  _M_open = _Seps::_S_braces().substr(0, 1);
5573  _M_close = _Seps::_S_braces().substr(1, 1);
5574  }
5575  if (__finished())
5576  return __parse_val(__m);
5577  __throw_format_error("format error: element format specifier"
5578  " cannot be provided when 'm' specifier is used");
5579  }
5580  else
5581  __throw_format_error("format error: 'm' specifier requires"
5582  " range of pairs or tuples of two elements");
5583  }
5584 
5585  if (__finished())
5586  return __parse_val();
5587 
5588  if (*__first == ':')
5589  {
5590  __pc.advance_to(++__first);
5591  __first = _M_fval.parse(__pc);
5592  }
5593 
5594  if (__finished())
5595  return __finalize();
5596 
5597  __format::__failed_to_parse_format_spec();
5598  }
5599 
5600  // We deviate from standard, that declares this as template accepting
5601  // unconstrained FormatContext type, which seems unimplementable.
5602  template<ranges::input_range _Rg, typename _Out>
5603  requires formattable<ranges::range_reference_t<_Rg>, _CharT> &&
5604  same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _Tp>
5605  typename basic_format_context<_Out, _CharT>::iterator
5606  format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
5607  {
5608  using _Range = remove_reference_t<_Rg>;
5609  if constexpr (__format::__simply_formattable_range<_Range, _CharT>)
5610  return _M_format<const _Range>(__rg, __fc);
5611  else
5612  return _M_format(__rg, __fc);
5613  }
5614 
5615  private:
5616  template<ranges::input_range _Rg, typename _Out>
5617  typename basic_format_context<_Out, _CharT>::iterator
5618  _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc) const
5619  {
5620  if constexpr (same_as<_Tp, _CharT>)
5621  if (_M_spec._M_type == __format::_Pres_str
5622  || _M_spec._M_type == __format::_Pres_esc)
5623  {
5624  __format::__formatter_str __fstr(_M_spec);
5625  return __fstr._M_format_range(__rg, __fc);
5626  }
5627  return __format::__format_padded(
5628  __fc, _M_spec,
5629  [this, &__rg](basic_format_context<_Out, _CharT>& __nfc)
5630  { return _M_format_elems(__rg, __nfc); });
5631  }
5632 
5633 
5634  template<ranges::input_range _Rg, typename _Out>
5635  typename basic_format_context<_Out, _CharT>::iterator
5636  _M_format_elems(_Rg& __rg,
5637  basic_format_context<_Out, _CharT>& __fc) const
5638  {
5639  auto __out = __format::__write(__fc.out(), _M_open);
5640 
5641  auto __first = ranges::begin(__rg);
5642  auto const __last = ranges::end(__rg);
5643  if (__first == __last)
5644  return __format::__write(__out, _M_close);
5645 
5646  __fc.advance_to(__out);
5647  __out = _M_fval.format(*__first, __fc);
5648  for (++__first; __first != __last; ++__first)
5649  {
5650  __out = __format::__write(__out, _M_sep);
5651  __fc.advance_to(__out);
5652  __out = _M_fval.format(*__first, __fc);
5653  }
5654 
5655  return __format::__write(__out, _M_close);
5656  }
5657 
5658  __format::_Spec<_CharT> _M_spec{};
5659  _String_view _M_open = _Seps::_S_squares().substr(0, 1);
5660  _String_view _M_close = _Seps::_S_squares().substr(1, 1);
5661  _String_view _M_sep = _Seps::_S_comma();
5662  formatter<_Tp, _CharT> _M_fval;
5663  };
5664 
5665  // In standard this is shown as inheriting from specialization of
5666  // exposition only specialization for range-default-formatter for
5667  // each range_format. We opt for simpler implementation.
5668  // [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr],
5669  // specializations for maps, sets, and strings
5670  template<ranges::input_range _Rg, __format::__char _CharT>
5671  requires (format_kind<_Rg> != range_format::disabled)
5672  && formattable<ranges::range_reference_t<_Rg>, _CharT>
5673  struct formatter<_Rg, _CharT>
5674  {
5675  private:
5676  static const bool _S_range_format_is_string =
5677  (format_kind<_Rg> == range_format::string)
5678  || (format_kind<_Rg> == range_format::debug_string);
5679  using _Vt = remove_cvref_t<
5680  ranges::range_reference_t<
5681  __format::__maybe_const_range<_Rg, _CharT>>>;
5682 
5683  static consteval bool _S_is_correct()
5684  {
5685  if constexpr (_S_range_format_is_string)
5686  static_assert(same_as<_Vt, _CharT>);
5687  return true;
5688  }
5689 
5690  static_assert(_S_is_correct());
5691 
5692  public:
5693  constexpr formatter() noexcept
5694  {
5695  using _Seps = __format::_Separators<_CharT>;
5696  if constexpr (format_kind<_Rg> == range_format::map)
5697  {
5698  static_assert(__format::__is_map_formattable<_Vt>);
5699  _M_under.set_brackets(_Seps::_S_braces().substr(0, 1),
5700  _Seps::_S_braces().substr(1, 1));
5701  _M_under.underlying().set_brackets({}, {});
5702  _M_under.underlying().set_separator(_Seps::_S_colon());
5703  }
5704  else if constexpr (format_kind<_Rg> == range_format::set)
5705  _M_under.set_brackets(_Seps::_S_braces().substr(0, 1),
5706  _Seps::_S_braces().substr(1, 1));
5707  }
5708 
5709  constexpr void
5710  set_separator(basic_string_view<_CharT> __sep) noexcept
5711  requires (format_kind<_Rg> == range_format::sequence)
5712  { _M_under.set_separator(__sep); }
5713 
5714  constexpr void
5715  set_brackets(basic_string_view<_CharT> __open,
5716  basic_string_view<_CharT> __close) noexcept
5717  requires (format_kind<_Rg> == range_format::sequence)
5718  { _M_under.set_brackets(__open, __close); }
5719 
5720  // We deviate from standard, that declares this as template accepting
5721  // unconstrained ParseContext type, which seems unimplementable.
5722  constexpr typename basic_format_parse_context<_CharT>::iterator
5723  parse(basic_format_parse_context<_CharT>& __pc)
5724  {
5725  auto __res = _M_under.parse(__pc);
5726  if constexpr (format_kind<_Rg> == range_format::debug_string)
5727  _M_under.set_debug_format();
5728  return __res;
5729  }
5730 
5731  // We deviate from standard, that declares this as template accepting
5732  // unconstrained FormatContext type, which seems unimplementable.
5733  template<typename _Out>
5734  typename basic_format_context<_Out, _CharT>::iterator
5735  format(__format::__maybe_const_range<_Rg, _CharT>& __rg,
5736  basic_format_context<_Out, _CharT>& __fc) const
5737  {
5738  if constexpr (_S_range_format_is_string)
5739  return _M_under._M_format_range(__rg, __fc);
5740  else
5741  return _M_under.format(__rg, __fc);
5742  }
5743 
5744  private:
5745  using _Formatter_under
5746  = __conditional_t<_S_range_format_is_string,
5747  __format::__formatter_str<_CharT>,
5748  range_formatter<_Vt, _CharT>>;
5749  _Formatter_under _M_under;
5750  };
5751 #endif // C++23 formatting ranges
5752 #undef _GLIBCXX_WIDEN
5753 
5754 _GLIBCXX_END_NAMESPACE_VERSION
5755 } // namespace std
5756 #endif // __cpp_lib_format
5757 #pragma GCC diagnostic pop
5758 #endif // _GLIBCXX_FORMAT