blob: dcedc3253626777651d645b7a03b3a0e617dffe2 [file] [log] [blame]
Mark de Weverdf5fd832020-11-26 19:12:18 +01001// -*- 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 {
Mark de Wevercba61372020-12-05 11:45:21 +010016 // [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
Mark de Wevercb50a052020-12-19 13:52:07 +010057 // [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
Mark de Wevercba61372020-12-05 11:45:21 +0100136 // [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
Mark de Weverdf5fd832020-11-26 19:12:18 +0100225 // [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 };
Mark de Wever6a67a5f2021-02-02 18:10:33 +0100231
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>;
Mark de Weverdf5fd832020-11-26 19:12:18 +0100263}
264
265*/
266
Mark de Weverbe38c382021-08-11 17:33:54 +0200267// Make sure all feature-test macros are available.
Mark de Wever14151d22021-07-30 14:35:37 -0400268#include <version>
Mark de Weverbe38c382021-08-11 17:33:54 +0200269// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
Mark de Wever14151d22021-07-30 14:35:37 -0400270#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
271
Mark de Weverdf5fd832020-11-26 19:12:18 +0100272#include <__config>
Mark de Wevercb50a052020-12-19 13:52:07 +0100273#include <__debug>
Mark de Wevercba61372020-12-05 11:45:21 +0100274#include <__format/format_arg.h>
275#include <__format/format_args.h>
276#include <__format/format_context.h>
Mark de Wever1aef5d02021-04-25 17:58:03 +0200277#include <__format/format_error.h>
Mark de Wevere26bdbb2021-04-25 18:23:42 +0200278#include <__format/format_parse_context.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100279#include <__format/format_string.h>
Mark de Wever96ff50c2020-12-14 17:39:15 +0100280#include <__format/parser_std_format_spec.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100281#include <__format/formatter.h>
282#include <__variant/monostate.h>
Mark de Wevercba61372020-12-05 11:45:21 +0100283#include <array>
Mark de Wevercb50a052020-12-19 13:52:07 +0100284#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
Mark de Wever8a0a1882021-07-25 09:18:53 +0200292
Mark de Weverdf5fd832020-11-26 19:12:18 +0100293#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Mark de Wevercba61372020-12-05 11:45:21 +0100294#pragma GCC system_header
Mark de Weverdf5fd832020-11-26 19:12:18 +0100295#endif
296
Mark de Wevercb50a052020-12-19 13:52:07 +0100297_LIBCPP_PUSH_MACROS
298#include <__undef_macros>
299
Mark de Wevercba61372020-12-05 11:45:21 +0100300_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
Mark de Wevercb50a052020-12-19 13:52:07 +0100339namespace __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
Louis Dionneaf2c8142021-09-09 14:43:02 -0400928#endif // _LIBCPP_HAS_NO_LOCALIZATION
Mark de Wevercb50a052020-12-19 13:52:07 +0100929
Mark de Wevercba61372020-12-05 11:45:21 +0100930#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
931#endif //_LIBCPP_STD_VER > 17
932
933_LIBCPP_END_NAMESPACE_STD
934
Mark de Wevercb50a052020-12-19 13:52:07 +0100935_LIBCPP_POP_MACROS
936
Mark de Wever14151d22021-07-30 14:35:37 -0400937#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
938
Mark de Weverdf5fd832020-11-26 19:12:18 +0100939#endif // _LIBCPP_FORMAT