blob: 19f642716b1b7f32f124c471dee31ae5c976ddd1 [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 Wever29307fd2020-12-14 17:39:15 +0100278#include <__format/format_fwd.h>
Mark de Wevere26bdbb2021-04-25 18:23:42 +0200279#include <__format/format_parse_context.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100280#include <__format/format_string.h>
281#include <__format/formatter.h>
Mark de Wever68a67712020-12-14 17:39:15 +0100282#include <__format/formatter_bool.h>
Mark de Weverb9d8e2f2020-12-14 17:39:15 +0100283#include <__format/formatter_char.h>
Mark de Wever29307fd2020-12-14 17:39:15 +0100284#include <__format/formatter_integer.h>
Mark de Weverf82551e2020-12-14 17:39:15 +0100285#include <__format/formatter_string.h>
286#include <__format/parser_std_format_spec.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100287#include <__variant/monostate.h>
Mark de Wevercba61372020-12-05 11:45:21 +0100288#include <array>
Mark de Wevercb50a052020-12-19 13:52:07 +0100289#include <concepts>
290#include <string>
291#include <string_view>
292#include <type_traits>
293
294#ifndef _LIBCPP_HAS_NO_LOCALIZATION
295#include <locale>
296#endif
Mark de Wever8a0a1882021-07-25 09:18:53 +0200297
Mark de Weverdf5fd832020-11-26 19:12:18 +0100298#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Mark de Wevercba61372020-12-05 11:45:21 +0100299#pragma GCC system_header
Mark de Weverdf5fd832020-11-26 19:12:18 +0100300#endif
301
Mark de Wevercb50a052020-12-19 13:52:07 +0100302_LIBCPP_PUSH_MACROS
303#include <__undef_macros>
304
Mark de Wevercba61372020-12-05 11:45:21 +0100305_LIBCPP_BEGIN_NAMESPACE_STD
306
307#if _LIBCPP_STD_VER > 17
308
309// TODO FMT Remove this once we require compilers with proper C++20 support.
310// If the compiler has no concepts support, the format header will be disabled.
311// Without concepts support enable_if needs to be used and that too much effort
312// to support compilers with partial C++20 support.
313#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
314
315// TODO FMT Evaluate which templates should be external templates. This
316// improves the efficiency of the header. However since the header is still
317// under heavy development and not all classes are stable it makes no sense
318// to do this optimization now.
319
320using format_args = basic_format_args<format_context>;
Louis Dionne89258142021-08-23 15:32:36 -0400321#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercba61372020-12-05 11:45:21 +0100322using wformat_args = basic_format_args<wformat_context>;
Louis Dionne89258142021-08-23 15:32:36 -0400323#endif
Mark de Wevercba61372020-12-05 11:45:21 +0100324
325template <class _OutIt, class _CharT>
326using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
327
328template <class _Context, class... _Args>
329struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
330 // TODO FMT Use a built-in array.
331 array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
332};
333
334template <class _Context = format_context, class... _Args>
335_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
336make_format_args(const _Args&... __args) {
337 return {basic_format_arg<_Context>(__args)...};
338}
339
Louis Dionne89258142021-08-23 15:32:36 -0400340#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercba61372020-12-05 11:45:21 +0100341template <class... _Args>
342_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
343make_wformat_args(const _Args&... __args) {
344 return _VSTD::make_format_args<wformat_context>(__args...);
345}
Louis Dionne89258142021-08-23 15:32:36 -0400346#endif
347
Mark de Wevercb50a052020-12-19 13:52:07 +0100348namespace __format {
Mark de Wevercb50a052020-12-19 13:52:07 +0100349
Mark de Wevercb50a052020-12-19 13:52:07 +0100350template <class _Tp, class _CharT>
351requires(is_arithmetic_v<_Tp> &&
352 !same_as<_Tp, bool>) struct _LIBCPP_HIDE_FROM_ABI
353 __formatter_arithmetic {
354 _LIBCPP_HIDE_FROM_ABI
355 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
356 // TODO FMT Implement
357 return __parse_ctx.begin();
358 }
359
360 _LIBCPP_HIDE_FROM_ABI
361 auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) {
362 return __handle_format(__value, __ctx);
363 }
364
365private:
366 template <class _Uv>
367 _LIBCPP_HIDDEN static string
368 __convert(_Uv __value) requires(same_as<_CharT, char>) {
369 return _VSTD::to_string(__value);
370 }
Louis Dionne89258142021-08-23 15:32:36 -0400371#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100372 template <class _Uv>
373 _LIBCPP_HIDDEN static wstring
374 __convert(_Uv __value) requires(same_as<_CharT, wchar_t>) {
375 return _VSTD::to_wstring(__value);
376 }
Louis Dionne89258142021-08-23 15:32:36 -0400377#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100378
379 template <class _Uv>
380 _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx)
381 -> decltype(__ctx.out())
Mark de Wevercb50a052020-12-19 13:52:07 +0100382 {
383 // TODO FMT Implement using formatting arguments
384 // TODO FMT Improve PoC since using std::to_string is inefficient.
385 // Note the code doesn't use std::string::iterator since the unit tests
386 // test with debug iterators and they fail with strings created from
387 // std::to_string.
388 auto __str = __convert(__value);
389 auto __out_it = __ctx.out();
390 for (size_t __i = 0, __e = __str.size(); __i != __e; ++__i)
391 *__out_it++ = __str[__i];
392 return __out_it;
393 }
Mark de Wevercb50a052020-12-19 13:52:07 +0100394};
395} // namespace __format
396
397// These specializations are helper stubs and not proper formatters.
398// TODO FMT Implement the proper formatter specializations.
399
Mark de Wevercb50a052020-12-19 13:52:07 +0100400// Floating point types.
401// TODO FMT There are no replacements for the floating point stubs due to not
402// having floating point support in std::to_chars yet. These stubs aren't
403// removed since they are useful for developing the real versions.
404// Ultimately the stubs should be implemented properly and this code can be
405// removed.
406#if 0
407template <class _CharT>
408struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT>
409 : public __format::__formatter_arithmetic<float, _CharT> {};
410template <class _CharT>
411struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
412 formatter<double, _CharT>
413 : public __format::__formatter_arithmetic<double, _CharT> {};
414template <class _CharT>
415struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
416 formatter<long double, _CharT>
417 : public __format::__formatter_arithmetic<long double, _CharT> {};
418#endif
419
420namespace __format {
421
422template <class _CharT, class _ParseCtx, class _Ctx>
423_LIBCPP_HIDE_FROM_ABI const _CharT*
424__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
425 _ParseCtx& __parse_ctx, _Ctx& __ctx) {
426 __format::__parse_number_result __r =
427 __format::__parse_arg_id(__begin, __end, __parse_ctx);
428
429 switch (*__r.__ptr) {
430 case _CharT(':'):
431 // The arg-id has a format-specifier, advance the input to the format-spec.
432 __parse_ctx.advance_to(__r.__ptr + 1);
433 break;
434 case _CharT('}'):
435 // The arg-id has no format-specifier.
436 __parse_ctx.advance_to(__r.__ptr);
437 break;
438 default:
439 __throw_format_error(
440 "The replacement field arg-id should terminate at a ':' or '}'");
441 }
442
443 _VSTD::visit_format_arg(
444 [&](auto __arg) {
445 if constexpr (same_as<decltype(__arg), monostate>)
446 __throw_format_error("Argument index out of bounds");
447 else {
448 formatter<decltype(__arg), _CharT> __formatter;
449 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
450 __ctx.advance_to(__formatter.format(__arg, __ctx));
451 }
452 },
453 __ctx.arg(__r.__value));
454
455 __begin = __parse_ctx.begin();
456 if (__begin == __end || *__begin != _CharT('}'))
457 __throw_format_error("The replacement field misses a terminating '}'");
458
459 return ++__begin;
460}
461
462template <class _ParseCtx, class _Ctx>
463_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
464__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
465 using _CharT = typename _ParseCtx::char_type;
466 static_assert(same_as<typename _Ctx::char_type, _CharT>);
467
468 const _CharT* __begin = __parse_ctx.begin();
469 const _CharT* __end = __parse_ctx.end();
470 typename _Ctx::iterator __out_it = __ctx.out();
471 while (__begin != __end) {
472 switch (*__begin) {
473 case _CharT('{'):
474 ++__begin;
475 if (__begin == __end)
476 __throw_format_error("The format string terminates at a '{'");
477
478 if (*__begin != _CharT('{')) [[likely]] {
479 __ctx.advance_to(_VSTD::move(__out_it));
480 __begin =
481 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
482 __out_it = __ctx.out();
483
484 // The output is written and __begin points to the next character. So
485 // start the next iteration.
486 continue;
487 }
488 // The string is an escape character.
489 break;
490
491 case _CharT('}'):
492 ++__begin;
493 if (__begin == __end || *__begin != _CharT('}'))
494 __throw_format_error(
495 "The format string contains an invalid escape sequence");
496
497 break;
498 }
499
500 // Copy the character to the output verbatim.
501 *__out_it++ = *__begin++;
502 }
503 return __out_it;
504}
505
506} // namespace __format
507
508template <class _OutIt, class _CharT>
509requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
510 __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt,
511 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
512 return __format::__vformat_to(
513 basic_format_parse_context{__fmt, __args.__size()},
514 _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
515}
516
517template <output_iterator<const char&> _OutIt>
518_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
519vformat_to(_OutIt __out_it, string_view __fmt,
520 format_args_t<type_identity_t<_OutIt>, char> __args) {
521 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
522}
523
Louis Dionne89258142021-08-23 15:32:36 -0400524#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100525template <output_iterator<const wchar_t&> _OutIt>
526_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
527vformat_to(_OutIt __out_it, wstring_view __fmt,
528 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
529 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
530}
Louis Dionne89258142021-08-23 15:32:36 -0400531#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100532
533template <output_iterator<const char&> _OutIt, class... _Args>
534_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
535format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
536 return _VSTD::vformat_to(
537 _VSTD::move(__out_it), __fmt,
538 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
539}
540
Louis Dionne89258142021-08-23 15:32:36 -0400541#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100542template <output_iterator<const wchar_t&> _OutIt, class... _Args>
543_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
544format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
545 return _VSTD::vformat_to(
546 _VSTD::move(__out_it), __fmt,
547 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
548 __args...));
549}
Louis Dionne89258142021-08-23 15:32:36 -0400550#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100551
552inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
553vformat(string_view __fmt, format_args __args) {
554 string __res;
555 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
556 return __res;
557}
558
Louis Dionne89258142021-08-23 15:32:36 -0400559#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100560inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
561vformat(wstring_view __fmt, wformat_args __args) {
562 wstring __res;
563 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
564 return __res;
565}
Louis Dionne89258142021-08-23 15:32:36 -0400566#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100567
568template <class... _Args>
569_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
570format(string_view __fmt, const _Args&... __args) {
571 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
572}
573
Louis Dionne89258142021-08-23 15:32:36 -0400574#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100575template <class... _Args>
576_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
577format(wstring_view __fmt, const _Args&... __args) {
578 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
579}
Louis Dionne89258142021-08-23 15:32:36 -0400580#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100581
582template <class _OutIt>
583struct _LIBCPP_TEMPLATE_VIS format_to_n_result {
584 _OutIt out;
585 iter_difference_t<_OutIt> size;
586};
587
588template <output_iterator<const char&> _OutIt, class... _Args>
589_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
590format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
591 const _Args&... __args) {
592 // TODO FMT Improve PoC: using std::string is inefficient.
593 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
594 iter_difference_t<_OutIt> __s = __str.size();
595 iter_difference_t<_OutIt> __m =
596 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
597 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
598 return {_VSTD::move(__out_it), __s};
599}
600
Louis Dionne89258142021-08-23 15:32:36 -0400601#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100602template <output_iterator<const wchar_t&> _OutIt, class... _Args>
603_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
604format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
605 const _Args&... __args) {
606 // TODO FMT Improve PoC: using std::string is inefficient.
607 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
608 iter_difference_t<_OutIt> __s = __str.size();
609 iter_difference_t<_OutIt> __m =
610 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
611 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
612 return {_VSTD::move(__out_it), __s};
613}
Louis Dionne89258142021-08-23 15:32:36 -0400614#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100615
616template <class... _Args>
617_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
618formatted_size(string_view __fmt, const _Args&... __args) {
619 // TODO FMT Improve PoC: using std::string is inefficient.
620 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
621}
622
Louis Dionne89258142021-08-23 15:32:36 -0400623#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100624template <class... _Args>
625_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
626formatted_size(wstring_view __fmt, const _Args&... __args) {
627 // TODO FMT Improve PoC: using std::string is inefficient.
628 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
629}
Louis Dionne89258142021-08-23 15:32:36 -0400630#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100631
632#ifndef _LIBCPP_HAS_NO_LOCALIZATION
633
634template <class _OutIt, class _CharT>
635requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
636 __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
637 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
638 return __format::__vformat_to(
639 basic_format_parse_context{__fmt, __args.__size()},
640 _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
641 _VSTD::move(__loc)));
642}
643
644template <output_iterator<const char&> _OutIt>
645_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
646vformat_to(_OutIt __out_it, locale __loc, string_view __fmt,
647 format_args_t<type_identity_t<_OutIt>, char> __args) {
648 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
649 __args);
650}
651
Louis Dionne89258142021-08-23 15:32:36 -0400652#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100653template <output_iterator<const wchar_t&> _OutIt>
654_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
655vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt,
656 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
657 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
658 __args);
659}
Louis Dionne89258142021-08-23 15:32:36 -0400660#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100661
662template <output_iterator<const char&> _OutIt, class... _Args>
663_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
664 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
665 return _VSTD::vformat_to(
666 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
667 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
668}
669
Louis Dionne89258142021-08-23 15:32:36 -0400670#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100671template <output_iterator<const wchar_t&> _OutIt, class... _Args>
672_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
673 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
674 return _VSTD::vformat_to(
675 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
676 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
677 __args...));
678}
Louis Dionne89258142021-08-23 15:32:36 -0400679#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100680
681inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
682vformat(locale __loc, string_view __fmt, format_args __args) {
683 string __res;
684 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
685 __args);
686 return __res;
687}
688
Louis Dionne89258142021-08-23 15:32:36 -0400689#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100690inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
691vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
692 wstring __res;
693 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
694 __args);
695 return __res;
696}
Louis Dionne89258142021-08-23 15:32:36 -0400697#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100698
699template <class... _Args>
700_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
701format(locale __loc, string_view __fmt, const _Args&... __args) {
702 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
703 _VSTD::make_format_args(__args...));
704}
705
Louis Dionne89258142021-08-23 15:32:36 -0400706#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100707template <class... _Args>
708_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
709format(locale __loc, wstring_view __fmt, const _Args&... __args) {
710 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
711 _VSTD::make_wformat_args(__args...));
712}
Louis Dionne89258142021-08-23 15:32:36 -0400713#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100714
715template <output_iterator<const char&> _OutIt, class... _Args>
716_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
717format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
718 string_view __fmt, const _Args&... __args) {
719 // TODO FMT Improve PoC: using std::string is inefficient.
720 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
721 _VSTD::make_format_args(__args...));
722 iter_difference_t<_OutIt> __s = __str.size();
723 iter_difference_t<_OutIt> __m =
724 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
725 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
726 return {_VSTD::move(__out_it), __s};
727}
728
Louis Dionne89258142021-08-23 15:32:36 -0400729#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100730template <output_iterator<const wchar_t&> _OutIt, class... _Args>
731_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
732format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
733 wstring_view __fmt, const _Args&... __args) {
734 // TODO FMT Improve PoC: using std::string is inefficient.
735 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
736 _VSTD::make_wformat_args(__args...));
737 iter_difference_t<_OutIt> __s = __str.size();
738 iter_difference_t<_OutIt> __m =
739 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
740 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
741 return {_VSTD::move(__out_it), __s};
742}
Louis Dionne89258142021-08-23 15:32:36 -0400743#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100744
745template <class... _Args>
746_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
747formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
748 // TODO FMT Improve PoC: using std::string is inefficient.
749 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
750 _VSTD::make_format_args(__args...))
751 .size();
752}
753
Louis Dionne89258142021-08-23 15:32:36 -0400754#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100755template <class... _Args>
756_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
757formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
758 // TODO FMT Improve PoC: using std::string is inefficient.
759 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
760 _VSTD::make_wformat_args(__args...))
761 .size();
762}
Louis Dionne89258142021-08-23 15:32:36 -0400763#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100764
Louis Dionneaf2c8142021-09-09 14:43:02 -0400765#endif // _LIBCPP_HAS_NO_LOCALIZATION
Mark de Wevercb50a052020-12-19 13:52:07 +0100766
Mark de Wevercba61372020-12-05 11:45:21 +0100767#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
768#endif //_LIBCPP_STD_VER > 17
769
770_LIBCPP_END_NAMESPACE_STD
771
Mark de Wevercb50a052020-12-19 13:52:07 +0100772_LIBCPP_POP_MACROS
773
Mark de Wever14151d22021-07-30 14:35:37 -0400774#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
775
Mark de Weverdf5fd832020-11-26 19:12:18 +0100776#endif // _LIBCPP_FORMAT