blob: ce16857665cd3e8a0ade409a9268c7bad6c32181 [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>
Mark de Wever63229c42021-11-13 19:43:32 +0100281#include <__format/format_to_n_result.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100282#include <__format/formatter.h>
Mark de Wever68a67712020-12-14 17:39:15 +0100283#include <__format/formatter_bool.h>
Mark de Weverb9d8e2f2020-12-14 17:39:15 +0100284#include <__format/formatter_char.h>
Mark de Wever29307fd2020-12-14 17:39:15 +0100285#include <__format/formatter_integer.h>
Mark de Weverf82551e2020-12-14 17:39:15 +0100286#include <__format/formatter_string.h>
287#include <__format/parser_std_format_spec.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100288#include <__variant/monostate.h>
Mark de Wevercba61372020-12-05 11:45:21 +0100289#include <array>
Mark de Wevercb50a052020-12-19 13:52:07 +0100290#include <concepts>
291#include <string>
292#include <string_view>
293#include <type_traits>
294
295#ifndef _LIBCPP_HAS_NO_LOCALIZATION
296#include <locale>
297#endif
Mark de Wever8a0a1882021-07-25 09:18:53 +0200298
Mark de Weverdf5fd832020-11-26 19:12:18 +0100299#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Mark de Wevercba61372020-12-05 11:45:21 +0100300#pragma GCC system_header
Mark de Weverdf5fd832020-11-26 19:12:18 +0100301#endif
302
Mark de Wevercb50a052020-12-19 13:52:07 +0100303_LIBCPP_PUSH_MACROS
304#include <__undef_macros>
305
Mark de Wevercba61372020-12-05 11:45:21 +0100306_LIBCPP_BEGIN_NAMESPACE_STD
307
308#if _LIBCPP_STD_VER > 17
309
310// TODO FMT Remove this once we require compilers with proper C++20 support.
311// If the compiler has no concepts support, the format header will be disabled.
312// Without concepts support enable_if needs to be used and that too much effort
313// to support compilers with partial C++20 support.
314#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
315
Mark de Wever88897732021-11-16 15:55:17 +0100316// TODO FMT Move the implementation in this file to its own granular headers.
317
Mark de Wevercba61372020-12-05 11:45:21 +0100318// TODO FMT Evaluate which templates should be external templates. This
319// improves the efficiency of the header. However since the header is still
320// under heavy development and not all classes are stable it makes no sense
321// to do this optimization now.
322
323using format_args = basic_format_args<format_context>;
Louis Dionne89258142021-08-23 15:32:36 -0400324#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercba61372020-12-05 11:45:21 +0100325using wformat_args = basic_format_args<wformat_context>;
Louis Dionne89258142021-08-23 15:32:36 -0400326#endif
Mark de Wevercba61372020-12-05 11:45:21 +0100327
328template <class _OutIt, class _CharT>
329using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
330
331template <class _Context, class... _Args>
332struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
333 // TODO FMT Use a built-in array.
334 array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
335};
336
337template <class _Context = format_context, class... _Args>
338_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
339make_format_args(const _Args&... __args) {
340 return {basic_format_arg<_Context>(__args)...};
341}
342
Louis Dionne89258142021-08-23 15:32:36 -0400343#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercba61372020-12-05 11:45:21 +0100344template <class... _Args>
345_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
346make_wformat_args(const _Args&... __args) {
347 return _VSTD::make_format_args<wformat_context>(__args...);
348}
Louis Dionne89258142021-08-23 15:32:36 -0400349#endif
350
Mark de Wevercb50a052020-12-19 13:52:07 +0100351namespace __format {
Mark de Wevercb50a052020-12-19 13:52:07 +0100352
Mark de Wevercb50a052020-12-19 13:52:07 +0100353template <class _Tp, class _CharT>
354requires(is_arithmetic_v<_Tp> &&
355 !same_as<_Tp, bool>) struct _LIBCPP_HIDE_FROM_ABI
356 __formatter_arithmetic {
357 _LIBCPP_HIDE_FROM_ABI
358 auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
359 // TODO FMT Implement
360 return __parse_ctx.begin();
361 }
362
363 _LIBCPP_HIDE_FROM_ABI
364 auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) {
365 return __handle_format(__value, __ctx);
366 }
367
368private:
369 template <class _Uv>
370 _LIBCPP_HIDDEN static string
371 __convert(_Uv __value) requires(same_as<_CharT, char>) {
372 return _VSTD::to_string(__value);
373 }
Louis Dionne89258142021-08-23 15:32:36 -0400374#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100375 template <class _Uv>
376 _LIBCPP_HIDDEN static wstring
377 __convert(_Uv __value) requires(same_as<_CharT, wchar_t>) {
378 return _VSTD::to_wstring(__value);
379 }
Louis Dionne89258142021-08-23 15:32:36 -0400380#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100381
382 template <class _Uv>
383 _LIBCPP_HIDDEN auto __handle_format(_Uv __value, auto& __ctx)
384 -> decltype(__ctx.out())
Mark de Wevercb50a052020-12-19 13:52:07 +0100385 {
386 // TODO FMT Implement using formatting arguments
387 // TODO FMT Improve PoC since using std::to_string is inefficient.
388 // Note the code doesn't use std::string::iterator since the unit tests
389 // test with debug iterators and they fail with strings created from
390 // std::to_string.
391 auto __str = __convert(__value);
392 auto __out_it = __ctx.out();
393 for (size_t __i = 0, __e = __str.size(); __i != __e; ++__i)
394 *__out_it++ = __str[__i];
395 return __out_it;
396 }
Mark de Wevercb50a052020-12-19 13:52:07 +0100397};
398} // namespace __format
399
400// These specializations are helper stubs and not proper formatters.
401// TODO FMT Implement the proper formatter specializations.
402
Mark de Wevercb50a052020-12-19 13:52:07 +0100403// Floating point types.
404// TODO FMT There are no replacements for the floating point stubs due to not
405// having floating point support in std::to_chars yet. These stubs aren't
406// removed since they are useful for developing the real versions.
407// Ultimately the stubs should be implemented properly and this code can be
408// removed.
409#if 0
410template <class _CharT>
411struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT>
412 : public __format::__formatter_arithmetic<float, _CharT> {};
413template <class _CharT>
414struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
415 formatter<double, _CharT>
416 : public __format::__formatter_arithmetic<double, _CharT> {};
417template <class _CharT>
418struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
419 formatter<long double, _CharT>
420 : public __format::__formatter_arithmetic<long double, _CharT> {};
421#endif
422
423namespace __format {
424
425template <class _CharT, class _ParseCtx, class _Ctx>
426_LIBCPP_HIDE_FROM_ABI const _CharT*
427__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
428 _ParseCtx& __parse_ctx, _Ctx& __ctx) {
429 __format::__parse_number_result __r =
430 __format::__parse_arg_id(__begin, __end, __parse_ctx);
431
432 switch (*__r.__ptr) {
433 case _CharT(':'):
434 // The arg-id has a format-specifier, advance the input to the format-spec.
435 __parse_ctx.advance_to(__r.__ptr + 1);
436 break;
437 case _CharT('}'):
438 // The arg-id has no format-specifier.
439 __parse_ctx.advance_to(__r.__ptr);
440 break;
441 default:
442 __throw_format_error(
443 "The replacement field arg-id should terminate at a ':' or '}'");
444 }
445
446 _VSTD::visit_format_arg(
447 [&](auto __arg) {
448 if constexpr (same_as<decltype(__arg), monostate>)
449 __throw_format_error("Argument index out of bounds");
450 else {
451 formatter<decltype(__arg), _CharT> __formatter;
452 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
453 __ctx.advance_to(__formatter.format(__arg, __ctx));
454 }
455 },
456 __ctx.arg(__r.__value));
457
458 __begin = __parse_ctx.begin();
459 if (__begin == __end || *__begin != _CharT('}'))
460 __throw_format_error("The replacement field misses a terminating '}'");
461
462 return ++__begin;
463}
464
465template <class _ParseCtx, class _Ctx>
466_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
467__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
468 using _CharT = typename _ParseCtx::char_type;
469 static_assert(same_as<typename _Ctx::char_type, _CharT>);
470
471 const _CharT* __begin = __parse_ctx.begin();
472 const _CharT* __end = __parse_ctx.end();
473 typename _Ctx::iterator __out_it = __ctx.out();
474 while (__begin != __end) {
475 switch (*__begin) {
476 case _CharT('{'):
477 ++__begin;
478 if (__begin == __end)
479 __throw_format_error("The format string terminates at a '{'");
480
481 if (*__begin != _CharT('{')) [[likely]] {
482 __ctx.advance_to(_VSTD::move(__out_it));
483 __begin =
484 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
485 __out_it = __ctx.out();
486
487 // The output is written and __begin points to the next character. So
488 // start the next iteration.
489 continue;
490 }
491 // The string is an escape character.
492 break;
493
494 case _CharT('}'):
495 ++__begin;
496 if (__begin == __end || *__begin != _CharT('}'))
497 __throw_format_error(
498 "The format string contains an invalid escape sequence");
499
500 break;
501 }
502
503 // Copy the character to the output verbatim.
504 *__out_it++ = *__begin++;
505 }
506 return __out_it;
507}
508
509} // namespace __format
510
511template <class _OutIt, class _CharT>
512requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
513 __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt,
514 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
515 return __format::__vformat_to(
516 basic_format_parse_context{__fmt, __args.__size()},
517 _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
518}
519
520template <output_iterator<const char&> _OutIt>
521_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
522vformat_to(_OutIt __out_it, string_view __fmt,
523 format_args_t<type_identity_t<_OutIt>, char> __args) {
524 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
525}
526
Louis Dionne89258142021-08-23 15:32:36 -0400527#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100528template <output_iterator<const wchar_t&> _OutIt>
529_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
530vformat_to(_OutIt __out_it, wstring_view __fmt,
531 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
532 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
533}
Louis Dionne89258142021-08-23 15:32:36 -0400534#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100535
536template <output_iterator<const char&> _OutIt, class... _Args>
537_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
538format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
539 return _VSTD::vformat_to(
540 _VSTD::move(__out_it), __fmt,
541 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
542}
543
Louis Dionne89258142021-08-23 15:32:36 -0400544#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100545template <output_iterator<const wchar_t&> _OutIt, class... _Args>
546_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
547format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
548 return _VSTD::vformat_to(
549 _VSTD::move(__out_it), __fmt,
550 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
551 __args...));
552}
Louis Dionne89258142021-08-23 15:32:36 -0400553#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100554
555inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
556vformat(string_view __fmt, format_args __args) {
557 string __res;
558 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
559 return __res;
560}
561
Louis Dionne89258142021-08-23 15:32:36 -0400562#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100563inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
564vformat(wstring_view __fmt, wformat_args __args) {
565 wstring __res;
566 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
567 return __res;
568}
Louis Dionne89258142021-08-23 15:32:36 -0400569#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100570
571template <class... _Args>
572_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
573format(string_view __fmt, const _Args&... __args) {
574 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
575}
576
Louis Dionne89258142021-08-23 15:32:36 -0400577#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100578template <class... _Args>
579_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
580format(wstring_view __fmt, const _Args&... __args) {
581 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
582}
Louis Dionne89258142021-08-23 15:32:36 -0400583#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100584
Mark de Wevercb50a052020-12-19 13:52:07 +0100585template <output_iterator<const char&> _OutIt, class... _Args>
586_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
587format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
588 const _Args&... __args) {
589 // TODO FMT Improve PoC: using std::string is inefficient.
590 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
591 iter_difference_t<_OutIt> __s = __str.size();
592 iter_difference_t<_OutIt> __m =
593 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
594 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
595 return {_VSTD::move(__out_it), __s};
596}
597
Louis Dionne89258142021-08-23 15:32:36 -0400598#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100599template <output_iterator<const wchar_t&> _OutIt, class... _Args>
600_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
601format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
602 const _Args&... __args) {
603 // TODO FMT Improve PoC: using std::string is inefficient.
604 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
605 iter_difference_t<_OutIt> __s = __str.size();
606 iter_difference_t<_OutIt> __m =
607 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
608 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
609 return {_VSTD::move(__out_it), __s};
610}
Louis Dionne89258142021-08-23 15:32:36 -0400611#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100612
613template <class... _Args>
614_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
615formatted_size(string_view __fmt, const _Args&... __args) {
616 // TODO FMT Improve PoC: using std::string is inefficient.
617 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
618}
619
Louis Dionne89258142021-08-23 15:32:36 -0400620#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100621template <class... _Args>
622_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
623formatted_size(wstring_view __fmt, const _Args&... __args) {
624 // TODO FMT Improve PoC: using std::string is inefficient.
625 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
626}
Louis Dionne89258142021-08-23 15:32:36 -0400627#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100628
629#ifndef _LIBCPP_HAS_NO_LOCALIZATION
630
631template <class _OutIt, class _CharT>
632requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
633 __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
634 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
635 return __format::__vformat_to(
636 basic_format_parse_context{__fmt, __args.__size()},
637 _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
638 _VSTD::move(__loc)));
639}
640
641template <output_iterator<const char&> _OutIt>
642_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
643vformat_to(_OutIt __out_it, locale __loc, string_view __fmt,
644 format_args_t<type_identity_t<_OutIt>, char> __args) {
645 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
646 __args);
647}
648
Louis Dionne89258142021-08-23 15:32:36 -0400649#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100650template <output_iterator<const wchar_t&> _OutIt>
651_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
652vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt,
653 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
654 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
655 __args);
656}
Louis Dionne89258142021-08-23 15:32:36 -0400657#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100658
659template <output_iterator<const char&> _OutIt, class... _Args>
660_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
661 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
662 return _VSTD::vformat_to(
663 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
664 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
665}
666
Louis Dionne89258142021-08-23 15:32:36 -0400667#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100668template <output_iterator<const wchar_t&> _OutIt, class... _Args>
669_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
670 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
671 return _VSTD::vformat_to(
672 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
673 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
674 __args...));
675}
Louis Dionne89258142021-08-23 15:32:36 -0400676#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100677
678inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
679vformat(locale __loc, string_view __fmt, format_args __args) {
680 string __res;
681 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
682 __args);
683 return __res;
684}
685
Louis Dionne89258142021-08-23 15:32:36 -0400686#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100687inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
688vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
689 wstring __res;
690 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
691 __args);
692 return __res;
693}
Louis Dionne89258142021-08-23 15:32:36 -0400694#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100695
696template <class... _Args>
697_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
698format(locale __loc, string_view __fmt, const _Args&... __args) {
699 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
700 _VSTD::make_format_args(__args...));
701}
702
Louis Dionne89258142021-08-23 15:32:36 -0400703#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100704template <class... _Args>
705_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
706format(locale __loc, wstring_view __fmt, const _Args&... __args) {
707 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
708 _VSTD::make_wformat_args(__args...));
709}
Louis Dionne89258142021-08-23 15:32:36 -0400710#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100711
712template <output_iterator<const char&> _OutIt, class... _Args>
713_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
714format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
715 string_view __fmt, const _Args&... __args) {
716 // TODO FMT Improve PoC: using std::string is inefficient.
717 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
718 _VSTD::make_format_args(__args...));
719 iter_difference_t<_OutIt> __s = __str.size();
720 iter_difference_t<_OutIt> __m =
721 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
722 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
723 return {_VSTD::move(__out_it), __s};
724}
725
Louis Dionne89258142021-08-23 15:32:36 -0400726#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100727template <output_iterator<const wchar_t&> _OutIt, class... _Args>
728_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
729format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
730 wstring_view __fmt, const _Args&... __args) {
731 // TODO FMT Improve PoC: using std::string is inefficient.
732 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
733 _VSTD::make_wformat_args(__args...));
734 iter_difference_t<_OutIt> __s = __str.size();
735 iter_difference_t<_OutIt> __m =
736 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
737 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
738 return {_VSTD::move(__out_it), __s};
739}
Louis Dionne89258142021-08-23 15:32:36 -0400740#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100741
742template <class... _Args>
743_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
744formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
745 // TODO FMT Improve PoC: using std::string is inefficient.
746 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
747 _VSTD::make_format_args(__args...))
748 .size();
749}
750
Louis Dionne89258142021-08-23 15:32:36 -0400751#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100752template <class... _Args>
753_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
754formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
755 // TODO FMT Improve PoC: using std::string is inefficient.
756 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
757 _VSTD::make_wformat_args(__args...))
758 .size();
759}
Louis Dionne89258142021-08-23 15:32:36 -0400760#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100761
Louis Dionneaf2c8142021-09-09 14:43:02 -0400762#endif // _LIBCPP_HAS_NO_LOCALIZATION
Mark de Wevercb50a052020-12-19 13:52:07 +0100763
Mark de Wevercba61372020-12-05 11:45:21 +0100764#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
765#endif //_LIBCPP_STD_VER > 17
766
767_LIBCPP_END_NAMESPACE_STD
768
Mark de Wevercb50a052020-12-19 13:52:07 +0100769_LIBCPP_POP_MACROS
770
Mark de Wever14151d22021-07-30 14:35:37 -0400771#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
772
Mark de Weverdf5fd832020-11-26 19:12:18 +0100773#endif // _LIBCPP_FORMAT