blob: 90547e2ce8daf56b67ee4a6590b01921ce496b4a [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>
280#include <__format/formatter.h>
281#include <__variant/monostate.h>
Mark de Wevercba61372020-12-05 11:45:21 +0100282#include <array>
Mark de Wevercb50a052020-12-19 13:52:07 +0100283#include <concepts>
284#include <string>
285#include <string_view>
286#include <type_traits>
287
288#ifndef _LIBCPP_HAS_NO_LOCALIZATION
289#include <locale>
290#endif
Mark de Wever8a0a1882021-07-25 09:18:53 +0200291
Mark de Weverdf5fd832020-11-26 19:12:18 +0100292#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Mark de Wevercba61372020-12-05 11:45:21 +0100293#pragma GCC system_header
Mark de Weverdf5fd832020-11-26 19:12:18 +0100294#endif
295
Mark de Wevercb50a052020-12-19 13:52:07 +0100296_LIBCPP_PUSH_MACROS
297#include <__undef_macros>
298
Mark de Wevercba61372020-12-05 11:45:21 +0100299_LIBCPP_BEGIN_NAMESPACE_STD
300
301#if _LIBCPP_STD_VER > 17
302
303// TODO FMT Remove this once we require compilers with proper C++20 support.
304// If the compiler has no concepts support, the format header will be disabled.
305// Without concepts support enable_if needs to be used and that too much effort
306// to support compilers with partial C++20 support.
307#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
308
309// TODO FMT Evaluate which templates should be external templates. This
310// improves the efficiency of the header. However since the header is still
311// under heavy development and not all classes are stable it makes no sense
312// to do this optimization now.
313
314using format_args = basic_format_args<format_context>;
315using wformat_args = basic_format_args<wformat_context>;
316
317template <class _OutIt, class _CharT>
318using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
319
320template <class _Context, class... _Args>
321struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
322 // TODO FMT Use a built-in array.
323 array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
324};
325
326template <class _Context = format_context, class... _Args>
327_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
328make_format_args(const _Args&... __args) {
329 return {basic_format_arg<_Context>(__args)...};
330}
331
332template <class... _Args>
333_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
334make_wformat_args(const _Args&... __args) {
335 return _VSTD::make_format_args<wformat_context>(__args...);
336}
337
Mark de Wevercb50a052020-12-19 13:52:07 +0100338namespace __format {
339template <class _Tp, class _CharT>
340struct _LIBCPP_TEMPLATE_VIS __formatter_char {
341 _LIBCPP_HIDE_FROM_ABI
342 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
343 // TODO FMT Implement this function.
344 return __parse_ctx.begin();
345 }
346
347 _LIBCPP_HIDE_FROM_ABI
348 auto format(_Tp __c, auto& __ctx) -> decltype(__ctx.out()) {
349 // TODO FMT Implement the parsed formatting arguments.
350 auto __out_it = __ctx.out();
351 *__out_it++ = _CharT(__c);
352 return __out_it;
353 }
354};
355
356template <class _CharT>
357struct _LIBCPP_TEMPLATE_VIS __formatter_c_string {
358 _LIBCPP_HIDE_FROM_ABI
359 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
360 // TODO FMT Implement this function.
361 return __parse_ctx.begin();
362 }
363
364 _LIBCPP_HIDE_FROM_ABI
365 auto format(const _CharT* __str, auto& __ctx) -> decltype(__ctx.out()) {
366 // TODO FMT Implement the parsed formatting arguments.
367 auto __out_it = __ctx.out();
368 while (*__str)
369 *__out_it++ = *__str++;
370 return __out_it;
371 }
372};
373
374template <class _CharT>
375struct _LIBCPP_TEMPLATE_VIS __formatter_string {
376 _LIBCPP_HIDE_FROM_ABI
377 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
378 // TODO FMT Implement this function.
379 return __parse_ctx.begin();
380 }
381
382 _LIBCPP_HIDE_FROM_ABI
383 auto format(basic_string_view<_CharT> __str, auto& __ctx)
384 -> decltype(__ctx.out()) {
385 // TODO FMT Implement the parsed formatting arguments.
386 auto __out_it = __ctx.out();
387 for (const auto __c : __str)
388 *__out_it++ = __c;
389 return __out_it;
390 }
391};
392
393template <class _Tp, class _CharT>
394requires(is_arithmetic_v<_Tp> &&
395 !same_as<_Tp, bool>) struct _LIBCPP_HIDE_FROM_ABI
396 __formatter_arithmetic {
397 _LIBCPP_HIDE_FROM_ABI
398 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
399 // TODO FMT Implement
400 return __parse_ctx.begin();
401 }
402
403 _LIBCPP_HIDE_FROM_ABI
404 auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) {
405 return __handle_format(__value, __ctx);
406 }
407
408private:
409 template <class _Uv>
410 _LIBCPP_HIDDEN static string
411 __convert(_Uv __value) requires(same_as<_CharT, char>) {
412 return _VSTD::to_string(__value);
413 }
414 template <class _Uv>
415 _LIBCPP_HIDDEN static wstring
416 __convert(_Uv __value) requires(same_as<_CharT, wchar_t>) {
417 return _VSTD::to_wstring(__value);
418 }
419
420 template <class _Uv>
421 _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx)
422 -> decltype(__ctx.out())
423#ifndef _LIBCPP_HAS_NO_INT128
424 requires(!same_as<_Uv, __int128_t> && !same_as<_Uv, __uint128_t>)
425#endif
426 {
427 // TODO FMT Implement using formatting arguments
428 // TODO FMT Improve PoC since using std::to_string is inefficient.
429 // Note the code doesn't use std::string::iterator since the unit tests
430 // test with debug iterators and they fail with strings created from
431 // std::to_string.
432 auto __str = __convert(__value);
433 auto __out_it = __ctx.out();
434 for (size_t __i = 0, __e = __str.size(); __i != __e; ++__i)
435 *__out_it++ = __str[__i];
436 return __out_it;
437 }
438#ifndef _LIBCPP_HAS_NO_INT128
439 template <class _Uv>
440 _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx)
441 -> decltype(__ctx.out()) requires(same_as<_Uv, __int128_t> ||
442 same_as<_Uv, __uint128_t>) {
443 using _To = conditional_t<is_signed_v<_Uv>, long long, unsigned long long>;
444 // TODO FMT Implement full 128-bit support.
445 if (__value < numeric_limits<_To>::min() ||
446 __value > numeric_limits<_To>::max())
447 __throw_format_error("128-bit value is outside of implemented range");
448
449 return __handle_format(static_cast<_To>(__value), __ctx);
450 }
451#endif
452};
453} // namespace __format
454
455// These specializations are helper stubs and not proper formatters.
456// TODO FMT Implement the proper formatter specializations.
457
458// [format.formatter.spec]/2.1 The specializations
459
460template <>
461struct _LIBCPP_TEMPLATE_VIS formatter<char, char>
462 : public __format::__formatter_char<char, char> {};
463
464template <>
465struct _LIBCPP_TEMPLATE_VIS formatter<char, wchar_t>
466 : public __format::__formatter_char<char, wchar_t> {};
467
468template <>
469struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t>
470 : public __format::__formatter_char<wchar_t, wchar_t> {};
471
472// [format.formatter.spec]/2.2 For each charT, the string type specializations
473
474template <class _CharT>
475struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT>
476 : public __format::__formatter_c_string<_CharT> {
477 using _Base = __format::__formatter_c_string<_CharT>;
478
479 _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx)
480 -> decltype(__ctx.out()) {
481 _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have "
482 "prevented an invalid pointer");
483 return _Base::format(__str, __ctx);
484 }
485};
486
487template <class _CharT>
488struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT*, _CharT>
489 : public __format::__formatter_c_string<_CharT> {};
490
491template <class _CharT, size_t _Size>
492struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT[_Size], _CharT>
493 : public __format::__formatter_string<_CharT> {
494 using _Base = __format::__formatter_string<_CharT>;
495
496 _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx)
497 -> decltype(__ctx.out()) {
498 return _Base::format(_VSTD::basic_string_view<_CharT>(__str, _Size), __ctx);
499 }
500};
501
502template <class _CharT, class _Traits, class _Allocator>
503struct _LIBCPP_TEMPLATE_VIS
504 formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
505 : public __format::__formatter_string<_CharT> {
506 using _Base = __format::__formatter_string<_CharT>;
507
508 _LIBCPP_HIDE_FROM_ABI auto
509 format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx)
510 -> decltype(__ctx.out()) {
511 return _Base::format(_VSTD::basic_string_view<_CharT>(__str), __ctx);
512 }
513};
514
515template <class _CharT, class _Traits>
516struct _LIBCPP_TEMPLATE_VIS
517 formatter<basic_string_view<_CharT, _Traits>, _CharT>
518 : public __format::__formatter_string<_CharT> {};
519
520// [format.formatter.spec]/2.3
521// For each charT, for each cv-unqualified arithmetic type ArithmeticT other
522// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
523
524// Boolean.
525template <class _CharT>
526struct _LIBCPP_TEMPLATE_VIS formatter<bool, _CharT> {
527 _LIBCPP_HIDE_FROM_ABI
528 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
529 // TODO FMT Implement
530 return __parse_ctx.begin();
531 }
532
533 _LIBCPP_HIDE_FROM_ABI
534 auto format(bool __b, auto& __ctx) -> decltype(__ctx.out()) {
535 // TODO FMT Implement using formatting arguments
536 auto __out_it = __ctx.out();
537 *__out_it++ = _CharT('0') + __b;
538 return __out_it;
539 }
540};
541
542// Signed integral types.
543template <class _CharT>
544struct _LIBCPP_TEMPLATE_VIS formatter<signed char, _CharT>
545 : public __format::__formatter_arithmetic<signed char, _CharT> {};
546template <class _CharT>
547struct _LIBCPP_TEMPLATE_VIS formatter<short, _CharT>
548 : public __format::__formatter_arithmetic<short, _CharT> {};
549template <class _CharT>
550struct _LIBCPP_TEMPLATE_VIS formatter<int, _CharT>
551 : public __format::__formatter_arithmetic<int, _CharT> {};
552template <class _CharT>
553struct _LIBCPP_TEMPLATE_VIS formatter<long, _CharT>
554 : public __format::__formatter_arithmetic<long, _CharT> {};
555template <class _CharT>
556struct _LIBCPP_TEMPLATE_VIS formatter<long long, _CharT>
557 : public __format::__formatter_arithmetic<long long, _CharT> {};
558#ifndef _LIBCPP_HAS_NO_INT128
559template <class _CharT>
560struct _LIBCPP_TEMPLATE_VIS formatter<__int128_t, _CharT>
561 : public __format::__formatter_arithmetic<__int128_t, _CharT> {};
562#endif
563
564// Unsigned integral types.
565template <class _CharT>
566struct _LIBCPP_TEMPLATE_VIS formatter<unsigned char, _CharT>
567 : public __format::__formatter_arithmetic<unsigned char, _CharT> {};
568template <class _CharT>
569struct _LIBCPP_TEMPLATE_VIS formatter<unsigned short, _CharT>
570 : public __format::__formatter_arithmetic<unsigned short, _CharT> {};
571template <class _CharT>
572struct _LIBCPP_TEMPLATE_VIS formatter<unsigned, _CharT>
573 : public __format::__formatter_arithmetic<unsigned, _CharT> {};
574template <class _CharT>
575struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long, _CharT>
576 : public __format::__formatter_arithmetic<unsigned long, _CharT> {};
577template <class _CharT>
578struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long long, _CharT>
579 : public __format::__formatter_arithmetic<unsigned long long, _CharT> {};
580#ifndef _LIBCPP_HAS_NO_INT128
581template <class _CharT>
582struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT>
583 : public __format::__formatter_arithmetic<__uint128_t, _CharT> {};
584#endif
585
586// Floating point types.
587// TODO FMT There are no replacements for the floating point stubs due to not
588// having floating point support in std::to_chars yet. These stubs aren't
589// removed since they are useful for developing the real versions.
590// Ultimately the stubs should be implemented properly and this code can be
591// removed.
592#if 0
593template <class _CharT>
594struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT>
595 : public __format::__formatter_arithmetic<float, _CharT> {};
596template <class _CharT>
597struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
598 formatter<double, _CharT>
599 : public __format::__formatter_arithmetic<double, _CharT> {};
600template <class _CharT>
601struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
602 formatter<long double, _CharT>
603 : public __format::__formatter_arithmetic<long double, _CharT> {};
604#endif
605
606namespace __format {
607
608template <class _CharT, class _ParseCtx, class _Ctx>
609_LIBCPP_HIDE_FROM_ABI const _CharT*
610__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
611 _ParseCtx& __parse_ctx, _Ctx& __ctx) {
612 __format::__parse_number_result __r =
613 __format::__parse_arg_id(__begin, __end, __parse_ctx);
614
615 switch (*__r.__ptr) {
616 case _CharT(':'):
617 // The arg-id has a format-specifier, advance the input to the format-spec.
618 __parse_ctx.advance_to(__r.__ptr + 1);
619 break;
620 case _CharT('}'):
621 // The arg-id has no format-specifier.
622 __parse_ctx.advance_to(__r.__ptr);
623 break;
624 default:
625 __throw_format_error(
626 "The replacement field arg-id should terminate at a ':' or '}'");
627 }
628
629 _VSTD::visit_format_arg(
630 [&](auto __arg) {
631 if constexpr (same_as<decltype(__arg), monostate>)
632 __throw_format_error("Argument index out of bounds");
633 else {
634 formatter<decltype(__arg), _CharT> __formatter;
635 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
636 __ctx.advance_to(__formatter.format(__arg, __ctx));
637 }
638 },
639 __ctx.arg(__r.__value));
640
641 __begin = __parse_ctx.begin();
642 if (__begin == __end || *__begin != _CharT('}'))
643 __throw_format_error("The replacement field misses a terminating '}'");
644
645 return ++__begin;
646}
647
648template <class _ParseCtx, class _Ctx>
649_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
650__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
651 using _CharT = typename _ParseCtx::char_type;
652 static_assert(same_as<typename _Ctx::char_type, _CharT>);
653
654 const _CharT* __begin = __parse_ctx.begin();
655 const _CharT* __end = __parse_ctx.end();
656 typename _Ctx::iterator __out_it = __ctx.out();
657 while (__begin != __end) {
658 switch (*__begin) {
659 case _CharT('{'):
660 ++__begin;
661 if (__begin == __end)
662 __throw_format_error("The format string terminates at a '{'");
663
664 if (*__begin != _CharT('{')) [[likely]] {
665 __ctx.advance_to(_VSTD::move(__out_it));
666 __begin =
667 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
668 __out_it = __ctx.out();
669
670 // The output is written and __begin points to the next character. So
671 // start the next iteration.
672 continue;
673 }
674 // The string is an escape character.
675 break;
676
677 case _CharT('}'):
678 ++__begin;
679 if (__begin == __end || *__begin != _CharT('}'))
680 __throw_format_error(
681 "The format string contains an invalid escape sequence");
682
683 break;
684 }
685
686 // Copy the character to the output verbatim.
687 *__out_it++ = *__begin++;
688 }
689 return __out_it;
690}
691
692} // namespace __format
693
694template <class _OutIt, class _CharT>
695requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
696 __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt,
697 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
698 return __format::__vformat_to(
699 basic_format_parse_context{__fmt, __args.__size()},
700 _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
701}
702
703template <output_iterator<const char&> _OutIt>
704_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
705vformat_to(_OutIt __out_it, string_view __fmt,
706 format_args_t<type_identity_t<_OutIt>, char> __args) {
707 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
708}
709
710template <output_iterator<const wchar_t&> _OutIt>
711_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
712vformat_to(_OutIt __out_it, wstring_view __fmt,
713 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
714 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
715}
716
717template <output_iterator<const char&> _OutIt, class... _Args>
718_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
719format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
720 return _VSTD::vformat_to(
721 _VSTD::move(__out_it), __fmt,
722 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
723}
724
725template <output_iterator<const wchar_t&> _OutIt, class... _Args>
726_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
727format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
728 return _VSTD::vformat_to(
729 _VSTD::move(__out_it), __fmt,
730 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
731 __args...));
732}
733
734inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
735vformat(string_view __fmt, format_args __args) {
736 string __res;
737 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
738 return __res;
739}
740
741inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
742vformat(wstring_view __fmt, wformat_args __args) {
743 wstring __res;
744 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
745 return __res;
746}
747
748template <class... _Args>
749_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
750format(string_view __fmt, const _Args&... __args) {
751 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
752}
753
754template <class... _Args>
755_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
756format(wstring_view __fmt, const _Args&... __args) {
757 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
758}
759
760template <class _OutIt>
761struct _LIBCPP_TEMPLATE_VIS format_to_n_result {
762 _OutIt out;
763 iter_difference_t<_OutIt> size;
764};
765
766template <output_iterator<const char&> _OutIt, class... _Args>
767_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
768format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
769 const _Args&... __args) {
770 // TODO FMT Improve PoC: using std::string is inefficient.
771 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
772 iter_difference_t<_OutIt> __s = __str.size();
773 iter_difference_t<_OutIt> __m =
774 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
775 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
776 return {_VSTD::move(__out_it), __s};
777}
778
779template <output_iterator<const wchar_t&> _OutIt, class... _Args>
780_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
781format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
782 const _Args&... __args) {
783 // TODO FMT Improve PoC: using std::string is inefficient.
784 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
785 iter_difference_t<_OutIt> __s = __str.size();
786 iter_difference_t<_OutIt> __m =
787 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
788 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
789 return {_VSTD::move(__out_it), __s};
790}
791
792template <class... _Args>
793_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
794formatted_size(string_view __fmt, const _Args&... __args) {
795 // TODO FMT Improve PoC: using std::string is inefficient.
796 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
797}
798
799template <class... _Args>
800_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
801formatted_size(wstring_view __fmt, const _Args&... __args) {
802 // TODO FMT Improve PoC: using std::string is inefficient.
803 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
804}
805
806#ifndef _LIBCPP_HAS_NO_LOCALIZATION
807
808template <class _OutIt, class _CharT>
809requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
810 __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
811 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
812 return __format::__vformat_to(
813 basic_format_parse_context{__fmt, __args.__size()},
814 _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
815 _VSTD::move(__loc)));
816}
817
818template <output_iterator<const char&> _OutIt>
819_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
820vformat_to(_OutIt __out_it, locale __loc, string_view __fmt,
821 format_args_t<type_identity_t<_OutIt>, char> __args) {
822 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
823 __args);
824}
825
826template <output_iterator<const wchar_t&> _OutIt>
827_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
828vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt,
829 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
830 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
831 __args);
832}
833
834template <output_iterator<const char&> _OutIt, class... _Args>
835_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
836 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
837 return _VSTD::vformat_to(
838 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
839 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
840}
841
842template <output_iterator<const wchar_t&> _OutIt, class... _Args>
843_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
844 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
845 return _VSTD::vformat_to(
846 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
847 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
848 __args...));
849}
850
851inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
852vformat(locale __loc, string_view __fmt, format_args __args) {
853 string __res;
854 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
855 __args);
856 return __res;
857}
858
859inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
860vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
861 wstring __res;
862 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
863 __args);
864 return __res;
865}
866
867template <class... _Args>
868_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
869format(locale __loc, string_view __fmt, const _Args&... __args) {
870 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
871 _VSTD::make_format_args(__args...));
872}
873
874template <class... _Args>
875_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
876format(locale __loc, wstring_view __fmt, const _Args&... __args) {
877 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
878 _VSTD::make_wformat_args(__args...));
879}
880
881template <output_iterator<const char&> _OutIt, class... _Args>
882_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
883format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
884 string_view __fmt, const _Args&... __args) {
885 // TODO FMT Improve PoC: using std::string is inefficient.
886 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
887 _VSTD::make_format_args(__args...));
888 iter_difference_t<_OutIt> __s = __str.size();
889 iter_difference_t<_OutIt> __m =
890 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
891 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
892 return {_VSTD::move(__out_it), __s};
893}
894
895template <output_iterator<const wchar_t&> _OutIt, class... _Args>
896_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
897format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
898 wstring_view __fmt, const _Args&... __args) {
899 // TODO FMT Improve PoC: using std::string is inefficient.
900 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
901 _VSTD::make_wformat_args(__args...));
902 iter_difference_t<_OutIt> __s = __str.size();
903 iter_difference_t<_OutIt> __m =
904 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
905 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
906 return {_VSTD::move(__out_it), __s};
907}
908
909template <class... _Args>
910_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
911formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
912 // TODO FMT Improve PoC: using std::string is inefficient.
913 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
914 _VSTD::make_format_args(__args...))
915 .size();
916}
917
918template <class... _Args>
919_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
920formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
921 // TODO FMT Improve PoC: using std::string is inefficient.
922 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
923 _VSTD::make_wformat_args(__args...))
924 .size();
925}
926
927#endif
928
Mark de Wevercba61372020-12-05 11:45:21 +0100929#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
930#endif //_LIBCPP_STD_VER > 17
931
932_LIBCPP_END_NAMESPACE_STD
933
Mark de Wevercb50a052020-12-19 13:52:07 +0100934_LIBCPP_POP_MACROS
935
Mark de Wever14151d22021-07-30 14:35:37 -0400936#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
937
Mark de Weverdf5fd832020-11-26 19:12:18 +0100938#endif // _LIBCPP_FORMAT