xref: /llvm-project-15.0.7/libcxx/include/format (revision 85d4e29f)
1// -*- C++ -*-
2//===--------------------------- format -----------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_FORMAT
11#define _LIBCPP_FORMAT
12
13/*
14
15namespace std {
16  // [format.context], class template basic_format_context
17  template<class Out, class charT>
18  class basic_format_context {
19    basic_format_args<basic_format_context> args_;      // exposition only
20    Out out_;                                           // exposition only
21
22  public:
23    using iterator = Out;
24    using char_type = charT;
25    template<class T> using formatter_type = formatter<T, charT>;
26
27    basic_format_arg<basic_format_context> arg(size_t id) const;
28    std::locale locale();
29
30    iterator out();
31    void advance_to(iterator it);
32  };
33  using format_context = basic_format_context<unspecified, char>;
34  using wformat_context = basic_format_context<unspecified, wchar_t>;
35
36  // [format.args], class template basic_format_args
37  template<class Context>
38  class basic_format_args {
39    size_t size_;                               // exposition only
40    const basic_format_arg<Context>* data_;     // exposition only
41
42  public:
43    basic_format_args() noexcept;
44
45    template<class... Args>
46      basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
47
48    basic_format_arg<Context> get(size_t i) const noexcept;
49  };
50  using format_args = basic_format_args<format_context>;
51  using wformat_args = basic_format_args<wformat_context>;
52
53
54  template<class Out, class charT>
55    using format_args_t = basic_format_args<basic_format_context<Out, charT>>;
56
57  // [format.functions], formatting functions
58  template<class... Args>
59    string format(string_view fmt, const Args&... args);
60  template<class... Args>
61    wstring format(wstring_view fmt, const Args&... args);
62  template<class... Args>
63    string format(const locale& loc, string_view fmt, const Args&... args);
64  template<class... Args>
65    wstring format(const locale& loc, wstring_view fmt, const Args&... args);
66
67  string vformat(string_view fmt, format_args args);
68  wstring vformat(wstring_view fmt, wformat_args args);
69  string vformat(const locale& loc, string_view fmt, format_args args);
70  wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
71
72  template<class Out, class... Args>
73    Out format_to(Out out, string_view fmt, const Args&... args);
74  template<class Out, class... Args>
75    Out format_to(Out out, wstring_view fmt, const Args&... args);
76  template<class Out, class... Args>
77    Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
78  template<class Out, class... Args>
79    Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
80
81  template<class Out>
82    Out vformat_to(Out out, string_view fmt,
83                   format_args_t<type_identity_t<Out>, char> args);
84  template<class Out>
85    Out vformat_to(Out out, wstring_view fmt,
86                   format_args_t<type_identity_t<Out>, wchar_t> args);
87  template<class Out>
88    Out vformat_to(Out out, const locale& loc, string_view fmt,
89                   format_args_t<type_identity_t<Out>, char> args);
90  template<class Out>
91    Out vformat_to(Out out, const locale& loc, wstring_view fmt,
92                   format_args_t<type_identity_t<Out>, wchar_t> args);
93
94  template<class Out> struct format_to_n_result {
95    Out out;
96    iter_difference_t<Out> size;
97  };
98
99 template<class Out, class... Args>
100    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
101                                        string_view fmt, const Args&... args);
102  template<class Out, class... Args>
103    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
104                                        wstring_view fmt, const Args&... args);
105  template<class Out, class... Args>
106    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
107                                        const locale& loc, string_view fmt,
108                                        const Args&... args);
109  template<class Out, class... Args>
110    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
111                                        const locale& loc, wstring_view fmt,
112                                        const Args&... args);
113
114  template<class... Args>
115    size_t formatted_size(string_view fmt, const Args&... args);
116  template<class... Args>
117    size_t formatted_size(wstring_view fmt, const Args&... args);
118  template<class... Args>
119    size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
120  template<class... Args>
121    size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
122
123  // [format.formatter], formatter
124  template<> struct formatter<char, char>;
125  template<> struct formatter<char, wchar_t>;
126  template<> struct formatter<wchar_t, wchar_t>;
127
128  template<> struct formatter<charT*, charT>;
129  template<> struct formatter<const charT*, charT>;
130  template<size_t N> struct formatter<const charT[N], charT>;
131  template<class traits, class Allocator>
132    struct formatter<basic_string<charT, traits, Allocator>, charT>;
133  template<class traits>
134    struct formatter<basic_string_view<charT, traits>, charT>;
135
136  // [format.parse.ctx], class template basic_format_parse_context
137  template<class charT>
138  class basic_format_parse_context {
139  public:
140    using char_type = charT;
141    using const_iterator = typename basic_string_view<charT>::const_iterator;
142    using iterator = const_iterator;
143
144  private:
145    iterator begin_;                                    // exposition only
146    iterator end_;                                      // exposition only
147    enum indexing { unknown, manual, automatic };       // exposition only
148    indexing indexing_;                                 // exposition only
149    size_t next_arg_id_;                                // exposition only
150    size_t num_args_;                                   // exposition only
151
152  public:
153    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
154                                                  size_t num_args = 0) noexcept;
155    basic_format_parse_context(const basic_format_parse_context&) = delete;
156    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
157
158    constexpr const_iterator begin() const noexcept;
159    constexpr const_iterator end() const noexcept;
160    constexpr void advance_to(const_iterator it);
161
162    constexpr size_t next_arg_id();
163    constexpr void check_arg_id(size_t id);
164  };
165  using format_parse_context = basic_format_parse_context<char>;
166  using wformat_parse_context = basic_format_parse_context<wchar_t>;
167
168  // [format.arguments], arguments
169  // [format.arg], class template basic_format_arg
170  template<class Context>
171  class basic_format_arg {
172  public:
173    class handle;
174
175  private:
176    using char_type = typename Context::char_type;                              // exposition only
177
178    variant<monostate, bool, char_type,
179            int, unsigned int, long long int, unsigned long long int,
180            float, double, long double,
181            const char_type*, basic_string_view<char_type>,
182            const void*, handle> value;                                         // exposition only
183
184    template<class T> explicit basic_format_arg(const T& v) noexcept;           // exposition only
185    explicit basic_format_arg(float n) noexcept;                                // exposition only
186    explicit basic_format_arg(double n) noexcept;                               // exposition only
187    explicit basic_format_arg(long double n) noexcept;                          // exposition only
188    explicit basic_format_arg(const char_type* s);                              // exposition only
189
190    template<class traits>
191      explicit basic_format_arg(
192        basic_string_view<char_type, traits> s) noexcept;                       // exposition only
193
194    template<class traits, class Allocator>
195      explicit basic_format_arg(
196        const basic_string<char_type, traits, Allocator>& s) noexcept;          // exposition only
197
198    explicit basic_format_arg(nullptr_t) noexcept;                              // exposition only
199
200    template<class T>
201      explicit basic_format_arg(const T* p) noexcept;                           // exposition only
202
203  public:
204    basic_format_arg() noexcept;
205
206    explicit operator bool() const noexcept;
207  };
208
209  template<class Visitor, class Context>
210    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
211
212  // [format.arg.store], class template format-arg-store
213  template<class Context, class... Args>
214  struct format-arg-store {      // exposition only
215    array<basic_format_arg<Context>, sizeof...(Args)> args;
216  };
217
218  template<class Context = format_context, class... Args>
219    format-arg-store<Context, Args...>
220      make_format_args(const Args&... args);
221  template<class... Args>
222    format-arg-store<wformat_context, Args...>
223      make_wformat_args(const Args&... args);
224
225  // [format.error], class format_error
226  class format_error : public runtime_error {
227  public:
228    explicit format_error(const string& what_arg);
229    explicit format_error(const char* what_arg);
230  };
231
232  // [format.parse.ctx], class template basic_format_parse_context
233  template<class charT>
234  class basic_format_parse_context {
235  public:
236    using char_type = charT;
237    using const_iterator = typename basic_string_view<charT>::const_iterator;
238    using iterator = const_iterator;
239
240  private:
241    iterator begin_;                                    // exposition only
242    iterator end_;                                      // exposition only
243    enum indexing { unknown, manual, automatic };       // exposition only
244    indexing indexing_;                                 // exposition only
245    size_t next_arg_id_;                                // exposition only
246    size_t num_args_;                                   // exposition only
247
248  public:
249    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
250                                                  size_t num_args = 0) noexcept;
251    basic_format_parse_context(const basic_format_parse_context&) = delete;
252    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
253
254    constexpr const_iterator begin() const noexcept;
255    constexpr const_iterator end() const noexcept;
256    constexpr void advance_to(const_iterator it);
257
258    constexpr size_t next_arg_id();
259    constexpr void check_arg_id(size_t id);
260  };
261  using format_parse_context = basic_format_parse_context<char>;
262  using wformat_parse_context = basic_format_parse_context<wchar_t>;
263}
264
265*/
266
267// Make sure all feature-test macros are available.
268#include <version>
269// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
270#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
271
272#include <__config>
273#include <__debug>
274#include <__format/format_arg.h>
275#include <__format/format_args.h>
276#include <__format/format_context.h>
277#include <__format/format_error.h>
278#include <__format/format_parse_context.h>
279#include <__format/format_string.h>
280#include <__format/parser_std_format_spec.h>
281#include <__format/formatter.h>
282#include <__variant/monostate.h>
283#include <array>
284#include <concepts>
285#include <string>
286#include <string_view>
287#include <type_traits>
288
289#ifndef _LIBCPP_HAS_NO_LOCALIZATION
290#include <locale>
291#endif
292
293#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
294#pragma GCC system_header
295#endif
296
297_LIBCPP_PUSH_MACROS
298#include <__undef_macros>
299
300_LIBCPP_BEGIN_NAMESPACE_STD
301
302#if _LIBCPP_STD_VER > 17
303
304// TODO FMT Remove this once we require compilers with proper C++20 support.
305// If the compiler has no concepts support, the format header will be disabled.
306// Without concepts support enable_if needs to be used and that too much effort
307// to support compilers with partial C++20 support.
308#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
309
310// TODO FMT Evaluate which templates should be external templates. This
311// improves the efficiency of the header. However since the header is still
312// under heavy development and not all classes are stable it makes no sense
313// to do this optimization now.
314
315using format_args = basic_format_args<format_context>;
316using wformat_args = basic_format_args<wformat_context>;
317
318template <class _OutIt, class _CharT>
319using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
320
321template <class _Context, class... _Args>
322struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
323  // TODO FMT Use a built-in array.
324  array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
325};
326
327template <class _Context = format_context, class... _Args>
328_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
329make_format_args(const _Args&... __args) {
330  return {basic_format_arg<_Context>(__args)...};
331}
332
333template <class... _Args>
334_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
335make_wformat_args(const _Args&... __args) {
336  return _VSTD::make_format_args<wformat_context>(__args...);
337}
338
339namespace __format {
340template <class _Tp, class _CharT>
341struct _LIBCPP_TEMPLATE_VIS __formatter_char {
342  _LIBCPP_HIDE_FROM_ABI
343  auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
344    // TODO FMT Implement this function.
345    return __parse_ctx.begin();
346  }
347
348  _LIBCPP_HIDE_FROM_ABI
349  auto format(_Tp __c, auto& __ctx) -> decltype(__ctx.out()) {
350    // TODO FMT Implement the parsed formatting arguments.
351    auto __out_it = __ctx.out();
352    *__out_it++ = _CharT(__c);
353    return __out_it;
354  }
355};
356
357template <class _CharT>
358struct _LIBCPP_TEMPLATE_VIS __formatter_c_string {
359  _LIBCPP_HIDE_FROM_ABI
360  auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
361    // TODO FMT Implement this function.
362    return __parse_ctx.begin();
363  }
364
365  _LIBCPP_HIDE_FROM_ABI
366  auto format(const _CharT* __str, auto& __ctx) -> decltype(__ctx.out()) {
367    // TODO FMT Implement the parsed formatting arguments.
368    auto __out_it = __ctx.out();
369    while (*__str)
370      *__out_it++ = *__str++;
371    return __out_it;
372  }
373};
374
375template <class _CharT>
376struct _LIBCPP_TEMPLATE_VIS __formatter_string {
377  _LIBCPP_HIDE_FROM_ABI
378  auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
379    // TODO FMT Implement this function.
380    return __parse_ctx.begin();
381  }
382
383  _LIBCPP_HIDE_FROM_ABI
384  auto format(basic_string_view<_CharT> __str, auto& __ctx)
385      -> decltype(__ctx.out()) {
386    // TODO FMT Implement the parsed formatting arguments.
387    auto __out_it = __ctx.out();
388    for (const auto __c : __str)
389      *__out_it++ = __c;
390    return __out_it;
391  }
392};
393
394template <class _Tp, class _CharT>
395requires(is_arithmetic_v<_Tp> &&
396         !same_as<_Tp, bool>) struct _LIBCPP_HIDE_FROM_ABI
397    __formatter_arithmetic {
398  _LIBCPP_HIDE_FROM_ABI
399  auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
400    // TODO FMT Implement
401    return __parse_ctx.begin();
402  }
403
404  _LIBCPP_HIDE_FROM_ABI
405  auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) {
406    return __handle_format(__value, __ctx);
407  }
408
409private:
410  template <class _Uv>
411  _LIBCPP_HIDDEN static string
412  __convert(_Uv __value) requires(same_as<_CharT, char>) {
413    return _VSTD::to_string(__value);
414  }
415  template <class _Uv>
416  _LIBCPP_HIDDEN static wstring
417  __convert(_Uv __value) requires(same_as<_CharT, wchar_t>) {
418    return _VSTD::to_wstring(__value);
419  }
420
421  template <class _Uv>
422  _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx)
423      -> decltype(__ctx.out())
424#ifndef _LIBCPP_HAS_NO_INT128
425          requires(!same_as<_Uv, __int128_t> && !same_as<_Uv, __uint128_t>)
426#endif
427  {
428    // TODO FMT Implement using formatting arguments
429    // TODO FMT Improve PoC since using std::to_string is inefficient.
430    // Note the code doesn't use std::string::iterator since the unit tests
431    // test with debug iterators and they fail with strings created from
432    // std::to_string.
433    auto __str = __convert(__value);
434    auto __out_it = __ctx.out();
435    for (size_t __i = 0, __e = __str.size(); __i != __e; ++__i)
436      *__out_it++ = __str[__i];
437    return __out_it;
438  }
439#ifndef _LIBCPP_HAS_NO_INT128
440  template <class _Uv>
441  _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx)
442      -> decltype(__ctx.out()) requires(same_as<_Uv, __int128_t> ||
443                                        same_as<_Uv, __uint128_t>) {
444    using _To = conditional_t<is_signed_v<_Uv>, long long, unsigned long long>;
445    // TODO FMT Implement full 128-bit support.
446    if (__value < numeric_limits<_To>::min() ||
447        __value > numeric_limits<_To>::max())
448      __throw_format_error("128-bit value is outside of implemented range");
449
450    return __handle_format(static_cast<_To>(__value), __ctx);
451  }
452#endif
453};
454} // namespace __format
455
456// These specializations are helper stubs and not proper formatters.
457// TODO FMT Implement the proper formatter specializations.
458
459// [format.formatter.spec]/2.1 The specializations
460
461template <>
462struct _LIBCPP_TEMPLATE_VIS formatter<char, char>
463    : public __format::__formatter_char<char, char> {};
464
465template <>
466struct _LIBCPP_TEMPLATE_VIS formatter<char, wchar_t>
467    : public __format::__formatter_char<char, wchar_t> {};
468
469template <>
470struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t>
471    : public __format::__formatter_char<wchar_t, wchar_t> {};
472
473// [format.formatter.spec]/2.2 For each charT, the string type specializations
474
475template <class _CharT>
476struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT>
477    : public __format::__formatter_c_string<_CharT> {
478  using _Base = __format::__formatter_c_string<_CharT>;
479
480  _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx)
481      -> decltype(__ctx.out()) {
482    _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have "
483                          "prevented an invalid pointer");
484    return _Base::format(__str, __ctx);
485  }
486};
487
488template <class _CharT>
489struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT*, _CharT>
490    : public __format::__formatter_c_string<_CharT> {};
491
492template <class _CharT, size_t _Size>
493struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT[_Size], _CharT>
494    : public __format::__formatter_string<_CharT> {
495  using _Base = __format::__formatter_string<_CharT>;
496
497  _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx)
498      -> decltype(__ctx.out()) {
499    return _Base::format(_VSTD::basic_string_view<_CharT>(__str, _Size), __ctx);
500  }
501};
502
503template <class _CharT, class _Traits, class _Allocator>
504struct _LIBCPP_TEMPLATE_VIS
505    formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
506    : public __format::__formatter_string<_CharT> {
507  using _Base = __format::__formatter_string<_CharT>;
508
509  _LIBCPP_HIDE_FROM_ABI auto
510  format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx)
511      -> decltype(__ctx.out()) {
512    return _Base::format(_VSTD::basic_string_view<_CharT>(__str), __ctx);
513  }
514};
515
516template <class _CharT, class _Traits>
517struct _LIBCPP_TEMPLATE_VIS
518    formatter<basic_string_view<_CharT, _Traits>, _CharT>
519    : public __format::__formatter_string<_CharT> {};
520
521// [format.formatter.spec]/2.3
522// For each charT, for each cv-unqualified arithmetic type ArithmeticT other
523// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
524
525// Boolean.
526template <class _CharT>
527struct _LIBCPP_TEMPLATE_VIS formatter<bool, _CharT> {
528  _LIBCPP_HIDE_FROM_ABI
529  auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
530    // TODO FMT Implement
531    return __parse_ctx.begin();
532  }
533
534  _LIBCPP_HIDE_FROM_ABI
535  auto format(bool __b, auto& __ctx) -> decltype(__ctx.out()) {
536    // TODO FMT Implement using formatting arguments
537    auto __out_it = __ctx.out();
538    *__out_it++ = _CharT('0') + __b;
539    return __out_it;
540  }
541};
542
543// Signed integral types.
544template <class _CharT>
545struct _LIBCPP_TEMPLATE_VIS formatter<signed char, _CharT>
546    : public __format::__formatter_arithmetic<signed char, _CharT> {};
547template <class _CharT>
548struct _LIBCPP_TEMPLATE_VIS formatter<short, _CharT>
549    : public __format::__formatter_arithmetic<short, _CharT> {};
550template <class _CharT>
551struct _LIBCPP_TEMPLATE_VIS formatter<int, _CharT>
552    : public __format::__formatter_arithmetic<int, _CharT> {};
553template <class _CharT>
554struct _LIBCPP_TEMPLATE_VIS formatter<long, _CharT>
555    : public __format::__formatter_arithmetic<long, _CharT> {};
556template <class _CharT>
557struct _LIBCPP_TEMPLATE_VIS formatter<long long, _CharT>
558    : public __format::__formatter_arithmetic<long long, _CharT> {};
559#ifndef _LIBCPP_HAS_NO_INT128
560template <class _CharT>
561struct _LIBCPP_TEMPLATE_VIS formatter<__int128_t, _CharT>
562    : public __format::__formatter_arithmetic<__int128_t, _CharT> {};
563#endif
564
565// Unsigned integral types.
566template <class _CharT>
567struct _LIBCPP_TEMPLATE_VIS formatter<unsigned char, _CharT>
568    : public __format::__formatter_arithmetic<unsigned char, _CharT> {};
569template <class _CharT>
570struct _LIBCPP_TEMPLATE_VIS formatter<unsigned short, _CharT>
571    : public __format::__formatter_arithmetic<unsigned short, _CharT> {};
572template <class _CharT>
573struct _LIBCPP_TEMPLATE_VIS formatter<unsigned, _CharT>
574    : public __format::__formatter_arithmetic<unsigned, _CharT> {};
575template <class _CharT>
576struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long, _CharT>
577    : public __format::__formatter_arithmetic<unsigned long, _CharT> {};
578template <class _CharT>
579struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long long, _CharT>
580    : public __format::__formatter_arithmetic<unsigned long long, _CharT> {};
581#ifndef _LIBCPP_HAS_NO_INT128
582template <class _CharT>
583struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT>
584    : public __format::__formatter_arithmetic<__uint128_t, _CharT> {};
585#endif
586
587// Floating point types.
588// TODO FMT There are no replacements for the floating point stubs due to not
589// having floating point support in std::to_chars yet. These stubs aren't
590// removed since they are useful for developing the real versions.
591// Ultimately the stubs should be implemented properly and this code can be
592// removed.
593#if 0
594template <class _CharT>
595struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT>
596    : public __format::__formatter_arithmetic<float, _CharT> {};
597template <class _CharT>
598struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
599    formatter<double, _CharT>
600    : public __format::__formatter_arithmetic<double, _CharT> {};
601template <class _CharT>
602struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
603    formatter<long double, _CharT>
604    : public __format::__formatter_arithmetic<long double, _CharT> {};
605#endif
606
607namespace __format {
608
609template <class _CharT, class _ParseCtx, class _Ctx>
610_LIBCPP_HIDE_FROM_ABI const _CharT*
611__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
612                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
613  __format::__parse_number_result __r =
614      __format::__parse_arg_id(__begin, __end, __parse_ctx);
615
616  switch (*__r.__ptr) {
617  case _CharT(':'):
618    // The arg-id has a format-specifier, advance the input to the format-spec.
619    __parse_ctx.advance_to(__r.__ptr + 1);
620    break;
621  case _CharT('}'):
622    // The arg-id has no format-specifier.
623    __parse_ctx.advance_to(__r.__ptr);
624    break;
625  default:
626    __throw_format_error(
627        "The replacement field arg-id should terminate at a ':' or '}'");
628  }
629
630  _VSTD::visit_format_arg(
631      [&](auto __arg) {
632        if constexpr (same_as<decltype(__arg), monostate>)
633          __throw_format_error("Argument index out of bounds");
634        else {
635          formatter<decltype(__arg), _CharT> __formatter;
636          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
637          __ctx.advance_to(__formatter.format(__arg, __ctx));
638        }
639      },
640      __ctx.arg(__r.__value));
641
642  __begin = __parse_ctx.begin();
643  if (__begin == __end || *__begin != _CharT('}'))
644    __throw_format_error("The replacement field misses a terminating '}'");
645
646  return ++__begin;
647}
648
649template <class _ParseCtx, class _Ctx>
650_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
651__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
652  using _CharT = typename _ParseCtx::char_type;
653  static_assert(same_as<typename _Ctx::char_type, _CharT>);
654
655  const _CharT* __begin = __parse_ctx.begin();
656  const _CharT* __end = __parse_ctx.end();
657  typename _Ctx::iterator __out_it = __ctx.out();
658  while (__begin != __end) {
659    switch (*__begin) {
660    case _CharT('{'):
661      ++__begin;
662      if (__begin == __end)
663        __throw_format_error("The format string terminates at a '{'");
664
665      if (*__begin != _CharT('{')) [[likely]] {
666        __ctx.advance_to(_VSTD::move(__out_it));
667        __begin =
668            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
669        __out_it = __ctx.out();
670
671        // The output is written and __begin points to the next character. So
672        // start the next iteration.
673        continue;
674      }
675      // The string is an escape character.
676      break;
677
678    case _CharT('}'):
679      ++__begin;
680      if (__begin == __end || *__begin != _CharT('}'))
681        __throw_format_error(
682            "The format string contains an invalid escape sequence");
683
684      break;
685    }
686
687    // Copy the character to the output verbatim.
688    *__out_it++ = *__begin++;
689  }
690  return __out_it;
691}
692
693} // namespace __format
694
695template <class _OutIt, class _CharT>
696requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
697    __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt,
698                 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
699  return __format::__vformat_to(
700      basic_format_parse_context{__fmt, __args.__size()},
701      _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
702}
703
704template <output_iterator<const char&> _OutIt>
705_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
706vformat_to(_OutIt __out_it, string_view __fmt,
707           format_args_t<type_identity_t<_OutIt>, char> __args) {
708  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
709}
710
711template <output_iterator<const wchar_t&> _OutIt>
712_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
713vformat_to(_OutIt __out_it, wstring_view __fmt,
714           format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
715  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
716}
717
718template <output_iterator<const char&> _OutIt, class... _Args>
719_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
720format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
721  return _VSTD::vformat_to(
722      _VSTD::move(__out_it), __fmt,
723      _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
724}
725
726template <output_iterator<const wchar_t&> _OutIt, class... _Args>
727_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
728format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
729  return _VSTD::vformat_to(
730      _VSTD::move(__out_it), __fmt,
731      _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
732          __args...));
733}
734
735inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
736vformat(string_view __fmt, format_args __args) {
737  string __res;
738  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
739  return __res;
740}
741
742inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
743vformat(wstring_view __fmt, wformat_args __args) {
744  wstring __res;
745  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
746  return __res;
747}
748
749template <class... _Args>
750_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
751format(string_view __fmt, const _Args&... __args) {
752  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
753}
754
755template <class... _Args>
756_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
757format(wstring_view __fmt, const _Args&... __args) {
758  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
759}
760
761template <class _OutIt>
762struct _LIBCPP_TEMPLATE_VIS format_to_n_result {
763  _OutIt out;
764  iter_difference_t<_OutIt> size;
765};
766
767template <output_iterator<const char&> _OutIt, class... _Args>
768_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
769format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
770            const _Args&... __args) {
771  // TODO FMT Improve PoC: using std::string is inefficient.
772  string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
773  iter_difference_t<_OutIt> __s = __str.size();
774  iter_difference_t<_OutIt> __m =
775      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
776  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
777  return {_VSTD::move(__out_it), __s};
778}
779
780template <output_iterator<const wchar_t&> _OutIt, class... _Args>
781_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
782format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
783            const _Args&... __args) {
784  // TODO FMT Improve PoC: using std::string is inefficient.
785  wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
786  iter_difference_t<_OutIt> __s = __str.size();
787  iter_difference_t<_OutIt> __m =
788      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
789  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
790  return {_VSTD::move(__out_it), __s};
791}
792
793template <class... _Args>
794_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
795formatted_size(string_view __fmt, const _Args&... __args) {
796  // TODO FMT Improve PoC: using std::string is inefficient.
797  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
798}
799
800template <class... _Args>
801_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
802formatted_size(wstring_view __fmt, const _Args&... __args) {
803  // TODO FMT Improve PoC: using std::string is inefficient.
804  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
805}
806
807#ifndef _LIBCPP_HAS_NO_LOCALIZATION
808
809template <class _OutIt, class _CharT>
810requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
811    __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
812                 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
813  return __format::__vformat_to(
814      basic_format_parse_context{__fmt, __args.__size()},
815      _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
816                                     _VSTD::move(__loc)));
817}
818
819template <output_iterator<const char&> _OutIt>
820_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
821vformat_to(_OutIt __out_it, locale __loc, string_view __fmt,
822           format_args_t<type_identity_t<_OutIt>, char> __args) {
823  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
824                             __args);
825}
826
827template <output_iterator<const wchar_t&> _OutIt>
828_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
829vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt,
830           format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
831  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
832                             __args);
833}
834
835template <output_iterator<const char&> _OutIt, class... _Args>
836_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
837    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
838  return _VSTD::vformat_to(
839      _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
840      _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
841}
842
843template <output_iterator<const wchar_t&> _OutIt, class... _Args>
844_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
845    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
846  return _VSTD::vformat_to(
847      _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
848      _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
849          __args...));
850}
851
852inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
853vformat(locale __loc, string_view __fmt, format_args __args) {
854  string __res;
855  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
856                    __args);
857  return __res;
858}
859
860inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
861vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
862  wstring __res;
863  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
864                    __args);
865  return __res;
866}
867
868template <class... _Args>
869_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
870format(locale __loc, string_view __fmt, const _Args&... __args) {
871  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
872                        _VSTD::make_format_args(__args...));
873}
874
875template <class... _Args>
876_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
877format(locale __loc, wstring_view __fmt, const _Args&... __args) {
878  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
879                        _VSTD::make_wformat_args(__args...));
880}
881
882template <output_iterator<const char&> _OutIt, class... _Args>
883_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
884format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
885            string_view __fmt, const _Args&... __args) {
886  // TODO FMT Improve PoC: using std::string is inefficient.
887  string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
888                                _VSTD::make_format_args(__args...));
889  iter_difference_t<_OutIt> __s = __str.size();
890  iter_difference_t<_OutIt> __m =
891      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
892  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
893  return {_VSTD::move(__out_it), __s};
894}
895
896template <output_iterator<const wchar_t&> _OutIt, class... _Args>
897_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
898format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
899            wstring_view __fmt, const _Args&... __args) {
900  // TODO FMT Improve PoC: using std::string is inefficient.
901  wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
902                                 _VSTD::make_wformat_args(__args...));
903  iter_difference_t<_OutIt> __s = __str.size();
904  iter_difference_t<_OutIt> __m =
905      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
906  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
907  return {_VSTD::move(__out_it), __s};
908}
909
910template <class... _Args>
911_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
912formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
913  // TODO FMT Improve PoC: using std::string is inefficient.
914  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
915                        _VSTD::make_format_args(__args...))
916      .size();
917}
918
919template <class... _Args>
920_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
921formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
922  // TODO FMT Improve PoC: using std::string is inefficient.
923  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
924                        _VSTD::make_wformat_args(__args...))
925      .size();
926}
927
928#endif // _LIBCPP_HAS_NO_LOCALIZATION
929
930#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
931#endif //_LIBCPP_STD_VER > 17
932
933_LIBCPP_END_NAMESPACE_STD
934
935_LIBCPP_POP_MACROS
936
937#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
938
939#endif // _LIBCPP_FORMAT
940