blob: 788b9c299abc029dc74147b7debe9e7323646a61 [file] [log] [blame]
Mark de Weverdf5fd832020-11-26 19:12:18 +01001// -*- C++ -*-
Louis Dionne9bd93882021-11-17 16:25:01 -05002//===----------------------------------------------------------------------===//
Mark de Weverdf5fd832020-11-26 19:12:18 +01003//
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
Mark de Wevercb50a052020-12-19 13:52:07 +010054 // [format.functions], formatting functions
55 template<class... Args>
56 string format(string_view fmt, const Args&... args);
57 template<class... Args>
58 wstring format(wstring_view fmt, const Args&... args);
59 template<class... Args>
60 string format(const locale& loc, string_view fmt, const Args&... args);
61 template<class... Args>
62 wstring format(const locale& loc, wstring_view fmt, const Args&... args);
63
64 string vformat(string_view fmt, format_args args);
65 wstring vformat(wstring_view fmt, wformat_args args);
66 string vformat(const locale& loc, string_view fmt, format_args args);
67 wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
68
69 template<class Out, class... Args>
70 Out format_to(Out out, string_view fmt, const Args&... args);
71 template<class Out, class... Args>
72 Out format_to(Out out, wstring_view fmt, const Args&... args);
73 template<class Out, class... Args>
74 Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
75 template<class Out, class... Args>
76 Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
77
78 template<class Out>
Mark de Weverd4f31252021-09-04 13:26:58 +020079 Out vformat_to(Out out, string_view fmt, format_args args);
Mark de Wevercb50a052020-12-19 13:52:07 +010080 template<class Out>
Mark de Weverd4f31252021-09-04 13:26:58 +020081 Out vformat_to(Out out, wstring_view fmt, wformat_args args);
Mark de Wevercb50a052020-12-19 13:52:07 +010082 template<class Out>
83 Out vformat_to(Out out, const locale& loc, string_view fmt,
Mark de Weverd4f31252021-09-04 13:26:58 +020084 format_args char> args);
Mark de Wevercb50a052020-12-19 13:52:07 +010085 template<class Out>
86 Out vformat_to(Out out, const locale& loc, wstring_view fmt,
Mark de Weverd4f31252021-09-04 13:26:58 +020087 wformat_args args);
Mark de Wevercb50a052020-12-19 13:52:07 +010088
89 template<class Out> struct format_to_n_result {
90 Out out;
91 iter_difference_t<Out> size;
92 };
93
94 template<class Out, class... Args>
95 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
96 string_view fmt, const Args&... args);
97 template<class Out, class... Args>
98 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
99 wstring_view fmt, const Args&... args);
100 template<class Out, class... Args>
101 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
102 const locale& loc, string_view fmt,
103 const Args&... args);
104 template<class Out, class... Args>
105 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
106 const locale& loc, wstring_view fmt,
107 const Args&... args);
108
109 template<class... Args>
110 size_t formatted_size(string_view fmt, const Args&... args);
111 template<class... Args>
112 size_t formatted_size(wstring_view fmt, const Args&... args);
113 template<class... Args>
114 size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
115 template<class... Args>
116 size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
117
118 // [format.formatter], formatter
119 template<> struct formatter<char, char>;
120 template<> struct formatter<char, wchar_t>;
121 template<> struct formatter<wchar_t, wchar_t>;
122
123 template<> struct formatter<charT*, charT>;
124 template<> struct formatter<const charT*, charT>;
125 template<size_t N> struct formatter<const charT[N], charT>;
126 template<class traits, class Allocator>
127 struct formatter<basic_string<charT, traits, Allocator>, charT>;
128 template<class traits>
129 struct formatter<basic_string_view<charT, traits>, charT>;
130
Mark de Wevercba61372020-12-05 11:45:21 +0100131 // [format.parse.ctx], class template basic_format_parse_context
132 template<class charT>
133 class basic_format_parse_context {
134 public:
135 using char_type = charT;
136 using const_iterator = typename basic_string_view<charT>::const_iterator;
137 using iterator = const_iterator;
138
139 private:
140 iterator begin_; // exposition only
141 iterator end_; // exposition only
142 enum indexing { unknown, manual, automatic }; // exposition only
143 indexing indexing_; // exposition only
144 size_t next_arg_id_; // exposition only
145 size_t num_args_; // exposition only
146
147 public:
148 constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
149 size_t num_args = 0) noexcept;
150 basic_format_parse_context(const basic_format_parse_context&) = delete;
151 basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
152
153 constexpr const_iterator begin() const noexcept;
154 constexpr const_iterator end() const noexcept;
155 constexpr void advance_to(const_iterator it);
156
157 constexpr size_t next_arg_id();
158 constexpr void check_arg_id(size_t id);
159 };
160 using format_parse_context = basic_format_parse_context<char>;
161 using wformat_parse_context = basic_format_parse_context<wchar_t>;
162
163 // [format.arguments], arguments
164 // [format.arg], class template basic_format_arg
165 template<class Context>
166 class basic_format_arg {
167 public:
168 class handle;
169
170 private:
171 using char_type = typename Context::char_type; // exposition only
172
173 variant<monostate, bool, char_type,
174 int, unsigned int, long long int, unsigned long long int,
175 float, double, long double,
176 const char_type*, basic_string_view<char_type>,
177 const void*, handle> value; // exposition only
178
179 template<class T> explicit basic_format_arg(const T& v) noexcept; // exposition only
180 explicit basic_format_arg(float n) noexcept; // exposition only
181 explicit basic_format_arg(double n) noexcept; // exposition only
182 explicit basic_format_arg(long double n) noexcept; // exposition only
183 explicit basic_format_arg(const char_type* s); // exposition only
184
185 template<class traits>
186 explicit basic_format_arg(
187 basic_string_view<char_type, traits> s) noexcept; // exposition only
188
189 template<class traits, class Allocator>
190 explicit basic_format_arg(
191 const basic_string<char_type, traits, Allocator>& s) noexcept; // exposition only
192
193 explicit basic_format_arg(nullptr_t) noexcept; // exposition only
194
195 template<class T>
196 explicit basic_format_arg(const T* p) noexcept; // exposition only
197
198 public:
199 basic_format_arg() noexcept;
200
201 explicit operator bool() const noexcept;
202 };
203
204 template<class Visitor, class Context>
205 see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
206
207 // [format.arg.store], class template format-arg-store
208 template<class Context, class... Args>
209 struct format-arg-store { // exposition only
210 array<basic_format_arg<Context>, sizeof...(Args)> args;
211 };
212
213 template<class Context = format_context, class... Args>
214 format-arg-store<Context, Args...>
215 make_format_args(const Args&... args);
216 template<class... Args>
217 format-arg-store<wformat_context, Args...>
218 make_wformat_args(const Args&... args);
219
Mark de Weverdf5fd832020-11-26 19:12:18 +0100220 // [format.error], class format_error
221 class format_error : public runtime_error {
222 public:
223 explicit format_error(const string& what_arg);
224 explicit format_error(const char* what_arg);
225 };
Mark de Wever6a67a5f2021-02-02 18:10:33 +0100226
227 // [format.parse.ctx], class template basic_format_parse_context
228 template<class charT>
229 class basic_format_parse_context {
230 public:
231 using char_type = charT;
232 using const_iterator = typename basic_string_view<charT>::const_iterator;
233 using iterator = const_iterator;
234
235 private:
236 iterator begin_; // exposition only
237 iterator end_; // exposition only
238 enum indexing { unknown, manual, automatic }; // exposition only
239 indexing indexing_; // exposition only
240 size_t next_arg_id_; // exposition only
241 size_t num_args_; // exposition only
242
243 public:
244 constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
245 size_t num_args = 0) noexcept;
246 basic_format_parse_context(const basic_format_parse_context&) = delete;
247 basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
248
249 constexpr const_iterator begin() const noexcept;
250 constexpr const_iterator end() const noexcept;
251 constexpr void advance_to(const_iterator it);
252
253 constexpr size_t next_arg_id();
254 constexpr void check_arg_id(size_t id);
255 };
256 using format_parse_context = basic_format_parse_context<char>;
257 using wformat_parse_context = basic_format_parse_context<wchar_t>;
Mark de Weverdf5fd832020-11-26 19:12:18 +0100258}
259
260*/
261
Mark de Weverbe38c382021-08-11 17:33:54 +0200262// Make sure all feature-test macros are available.
Mark de Wever14151d22021-07-30 14:35:37 -0400263#include <version>
Mark de Weverbe38c382021-08-11 17:33:54 +0200264// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
Mark de Wever14151d22021-07-30 14:35:37 -0400265#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
266
Mark de Weverdf5fd832020-11-26 19:12:18 +0100267#include <__config>
Mark de Wevercb50a052020-12-19 13:52:07 +0100268#include <__debug>
Mark de Wevercba61372020-12-05 11:45:21 +0100269#include <__format/format_arg.h>
270#include <__format/format_args.h>
271#include <__format/format_context.h>
Mark de Wever1aef5d02021-04-25 17:58:03 +0200272#include <__format/format_error.h>
Mark de Wever29307fd2020-12-14 17:39:15 +0100273#include <__format/format_fwd.h>
Mark de Wevere26bdbb2021-04-25 18:23:42 +0200274#include <__format/format_parse_context.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100275#include <__format/format_string.h>
Mark de Wever63229c42021-11-13 19:43:32 +0100276#include <__format/format_to_n_result.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100277#include <__format/formatter.h>
Mark de Wever68a67712020-12-14 17:39:15 +0100278#include <__format/formatter_bool.h>
Mark de Weverb9d8e2f2020-12-14 17:39:15 +0100279#include <__format/formatter_char.h>
Mark de Wever29307fd2020-12-14 17:39:15 +0100280#include <__format/formatter_integer.h>
Mark de Weverf82551e2020-12-14 17:39:15 +0100281#include <__format/formatter_string.h>
282#include <__format/parser_std_format_spec.h>
Mark de Wevercb50a052020-12-19 13:52:07 +0100283#include <__variant/monostate.h>
Mark de Wevercba61372020-12-05 11:45:21 +0100284#include <array>
Mark de Wevercb50a052020-12-19 13:52:07 +0100285#include <concepts>
286#include <string>
287#include <string_view>
288#include <type_traits>
289
290#ifndef _LIBCPP_HAS_NO_LOCALIZATION
291#include <locale>
292#endif
Mark de Wever8a0a1882021-07-25 09:18:53 +0200293
Mark de Weverdf5fd832020-11-26 19:12:18 +0100294#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Mark de Wevercba61372020-12-05 11:45:21 +0100295#pragma GCC system_header
Mark de Weverdf5fd832020-11-26 19:12:18 +0100296#endif
297
Mark de Wevercb50a052020-12-19 13:52:07 +0100298_LIBCPP_PUSH_MACROS
299#include <__undef_macros>
300
Mark de Wevercba61372020-12-05 11:45:21 +0100301_LIBCPP_BEGIN_NAMESPACE_STD
302
303#if _LIBCPP_STD_VER > 17
304
305// TODO FMT Remove this once we require compilers with proper C++20 support.
306// If the compiler has no concepts support, the format header will be disabled.
307// Without concepts support enable_if needs to be used and that too much effort
308// to support compilers with partial C++20 support.
309#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
310
Mark de Wever88897732021-11-16 15:55:17 +0100311// TODO FMT Move the implementation in this file to its own granular headers.
312
Mark de Wevercba61372020-12-05 11:45:21 +0100313// TODO FMT Evaluate which templates should be external templates. This
314// improves the efficiency of the header. However since the header is still
315// under heavy development and not all classes are stable it makes no sense
316// to do this optimization now.
317
318using format_args = basic_format_args<format_context>;
Louis Dionne89258142021-08-23 15:32:36 -0400319#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercba61372020-12-05 11:45:21 +0100320using wformat_args = basic_format_args<wformat_context>;
Louis Dionne89258142021-08-23 15:32:36 -0400321#endif
Mark de Wevercba61372020-12-05 11:45:21 +0100322
Mark de Wevercba61372020-12-05 11:45:21 +0100323template <class _Context, class... _Args>
324struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
325 // TODO FMT Use a built-in array.
326 array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
327};
328
329template <class _Context = format_context, class... _Args>
330_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
331make_format_args(const _Args&... __args) {
332 return {basic_format_arg<_Context>(__args)...};
333}
334
Louis Dionne89258142021-08-23 15:32:36 -0400335#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercba61372020-12-05 11:45:21 +0100336template <class... _Args>
337_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
338make_wformat_args(const _Args&... __args) {
339 return _VSTD::make_format_args<wformat_context>(__args...);
340}
Louis Dionne89258142021-08-23 15:32:36 -0400341#endif
342
Mark de Wevercb50a052020-12-19 13:52:07 +0100343namespace __format {
Mark de Wevercb50a052020-12-19 13:52:07 +0100344
Mark de Wevercb50a052020-12-19 13:52:07 +0100345template <class _CharT, class _ParseCtx, class _Ctx>
346_LIBCPP_HIDE_FROM_ABI const _CharT*
347__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
348 _ParseCtx& __parse_ctx, _Ctx& __ctx) {
349 __format::__parse_number_result __r =
350 __format::__parse_arg_id(__begin, __end, __parse_ctx);
351
352 switch (*__r.__ptr) {
353 case _CharT(':'):
354 // The arg-id has a format-specifier, advance the input to the format-spec.
355 __parse_ctx.advance_to(__r.__ptr + 1);
356 break;
357 case _CharT('}'):
358 // The arg-id has no format-specifier.
359 __parse_ctx.advance_to(__r.__ptr);
360 break;
361 default:
362 __throw_format_error(
363 "The replacement field arg-id should terminate at a ':' or '}'");
364 }
365
366 _VSTD::visit_format_arg(
367 [&](auto __arg) {
368 if constexpr (same_as<decltype(__arg), monostate>)
369 __throw_format_error("Argument index out of bounds");
370 else {
371 formatter<decltype(__arg), _CharT> __formatter;
372 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
373 __ctx.advance_to(__formatter.format(__arg, __ctx));
374 }
375 },
376 __ctx.arg(__r.__value));
377
378 __begin = __parse_ctx.begin();
379 if (__begin == __end || *__begin != _CharT('}'))
380 __throw_format_error("The replacement field misses a terminating '}'");
381
382 return ++__begin;
383}
384
385template <class _ParseCtx, class _Ctx>
386_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
387__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
388 using _CharT = typename _ParseCtx::char_type;
389 static_assert(same_as<typename _Ctx::char_type, _CharT>);
390
391 const _CharT* __begin = __parse_ctx.begin();
392 const _CharT* __end = __parse_ctx.end();
393 typename _Ctx::iterator __out_it = __ctx.out();
394 while (__begin != __end) {
395 switch (*__begin) {
396 case _CharT('{'):
397 ++__begin;
398 if (__begin == __end)
399 __throw_format_error("The format string terminates at a '{'");
400
401 if (*__begin != _CharT('{')) [[likely]] {
402 __ctx.advance_to(_VSTD::move(__out_it));
403 __begin =
404 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
405 __out_it = __ctx.out();
406
407 // The output is written and __begin points to the next character. So
408 // start the next iteration.
409 continue;
410 }
411 // The string is an escape character.
412 break;
413
414 case _CharT('}'):
415 ++__begin;
416 if (__begin == __end || *__begin != _CharT('}'))
417 __throw_format_error(
418 "The format string contains an invalid escape sequence");
419
420 break;
421 }
422
423 // Copy the character to the output verbatim.
424 *__out_it++ = *__begin++;
425 }
426 return __out_it;
427}
428
429} // namespace __format
430
Mark de Weverd4f31252021-09-04 13:26:58 +0200431template <class _OutIt, class _CharT, class _FormatOutIt>
Mark de Wevercb50a052020-12-19 13:52:07 +0100432requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
Mark de Weverd4f31252021-09-04 13:26:58 +0200433 __vformat_to(
434 _OutIt __out_it, basic_string_view<_CharT> __fmt,
435 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
436 if constexpr (same_as<_OutIt, _FormatOutIt>)
437 return _VSTD::__format::__vformat_to(
438 basic_format_parse_context{__fmt, __args.__size()},
439 _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
440 else {
441 basic_string<_CharT> __str;
442 _VSTD::__format::__vformat_to(
443 basic_format_parse_context{__fmt, __args.__size()},
444 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args));
445 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
446 }
Mark de Wevercb50a052020-12-19 13:52:07 +0100447}
448
449template <output_iterator<const char&> _OutIt>
Mark de Weverd4f31252021-09-04 13:26:58 +0200450_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
451vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
Mark de Wevercb50a052020-12-19 13:52:07 +0100452 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
453}
454
Louis Dionne89258142021-08-23 15:32:36 -0400455#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100456template <output_iterator<const wchar_t&> _OutIt>
Mark de Weverd4f31252021-09-04 13:26:58 +0200457_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
458vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
Mark de Wevercb50a052020-12-19 13:52:07 +0100459 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
460}
Louis Dionne89258142021-08-23 15:32:36 -0400461#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100462
463template <output_iterator<const char&> _OutIt, class... _Args>
Mark de Weverd4f31252021-09-04 13:26:58 +0200464_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
Mark de Wevercb50a052020-12-19 13:52:07 +0100465format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
Mark de Weverd4f31252021-09-04 13:26:58 +0200466 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
467 _VSTD::make_format_args(__args...));
Mark de Wevercb50a052020-12-19 13:52:07 +0100468}
469
Louis Dionne89258142021-08-23 15:32:36 -0400470#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100471template <output_iterator<const wchar_t&> _OutIt, class... _Args>
Mark de Weverd4f31252021-09-04 13:26:58 +0200472_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
Mark de Wevercb50a052020-12-19 13:52:07 +0100473format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
Mark de Weverd4f31252021-09-04 13:26:58 +0200474 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
475 _VSTD::make_wformat_args(__args...));
Mark de Wevercb50a052020-12-19 13:52:07 +0100476}
Louis Dionne89258142021-08-23 15:32:36 -0400477#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100478
Mark de Weverd4f31252021-09-04 13:26:58 +0200479_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
Mark de Wevercb50a052020-12-19 13:52:07 +0100480vformat(string_view __fmt, format_args __args) {
481 string __res;
482 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
483 return __res;
484}
485
Louis Dionne89258142021-08-23 15:32:36 -0400486#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverd4f31252021-09-04 13:26:58 +0200487_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
Mark de Wevercb50a052020-12-19 13:52:07 +0100488vformat(wstring_view __fmt, wformat_args __args) {
489 wstring __res;
490 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
491 return __res;
492}
Louis Dionne89258142021-08-23 15:32:36 -0400493#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100494
495template <class... _Args>
Mark de Weverd4f31252021-09-04 13:26:58 +0200496_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
Mark de Wevercb50a052020-12-19 13:52:07 +0100497format(string_view __fmt, const _Args&... __args) {
498 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
499}
500
Louis Dionne89258142021-08-23 15:32:36 -0400501#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100502template <class... _Args>
Mark de Weverd4f31252021-09-04 13:26:58 +0200503_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
Mark de Wevercb50a052020-12-19 13:52:07 +0100504format(wstring_view __fmt, const _Args&... __args) {
505 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
506}
Louis Dionne89258142021-08-23 15:32:36 -0400507#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100508
Mark de Wevercb50a052020-12-19 13:52:07 +0100509template <output_iterator<const char&> _OutIt, class... _Args>
510_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
511format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
512 const _Args&... __args) {
513 // TODO FMT Improve PoC: using std::string is inefficient.
514 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
515 iter_difference_t<_OutIt> __s = __str.size();
516 iter_difference_t<_OutIt> __m =
517 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
518 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
519 return {_VSTD::move(__out_it), __s};
520}
521
Louis Dionne89258142021-08-23 15:32:36 -0400522#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100523template <output_iterator<const wchar_t&> _OutIt, class... _Args>
524_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
525format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
526 const _Args&... __args) {
527 // TODO FMT Improve PoC: using std::string is inefficient.
528 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
529 iter_difference_t<_OutIt> __s = __str.size();
530 iter_difference_t<_OutIt> __m =
531 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
532 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
533 return {_VSTD::move(__out_it), __s};
534}
Louis Dionne89258142021-08-23 15:32:36 -0400535#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100536
537template <class... _Args>
538_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
539formatted_size(string_view __fmt, const _Args&... __args) {
540 // TODO FMT Improve PoC: using std::string is inefficient.
541 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
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 <class... _Args>
546_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
547formatted_size(wstring_view __fmt, const _Args&... __args) {
548 // TODO FMT Improve PoC: using std::string is inefficient.
549 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
550}
Louis Dionne89258142021-08-23 15:32:36 -0400551#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100552
553#ifndef _LIBCPP_HAS_NO_LOCALIZATION
554
Mark de Weverd4f31252021-09-04 13:26:58 +0200555template <class _OutIt, class _CharT, class _FormatOutIt>
Mark de Wevercb50a052020-12-19 13:52:07 +0100556requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
Mark de Weverd4f31252021-09-04 13:26:58 +0200557 __vformat_to(
558 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
559 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
560 if constexpr (same_as<_OutIt, _FormatOutIt>)
561 return _VSTD::__format::__vformat_to(
562 basic_format_parse_context{__fmt, __args.__size()},
563 _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
564 _VSTD::move(__loc)));
565 else {
566 basic_string<_CharT> __str;
567 _VSTD::__format::__vformat_to(
568 basic_format_parse_context{__fmt, __args.__size()},
569 _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args,
570 _VSTD::move(__loc)));
571 return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
572 }
Mark de Wevercb50a052020-12-19 13:52:07 +0100573}
574
575template <output_iterator<const char&> _OutIt>
Mark de Weverd4f31252021-09-04 13:26:58 +0200576_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
577 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
Mark de Wevercb50a052020-12-19 13:52:07 +0100578 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
579 __args);
580}
581
Louis Dionne89258142021-08-23 15:32:36 -0400582#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100583template <output_iterator<const wchar_t&> _OutIt>
Mark de Weverd4f31252021-09-04 13:26:58 +0200584_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
585 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
Mark de Wevercb50a052020-12-19 13:52:07 +0100586 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
587 __args);
588}
Louis Dionne89258142021-08-23 15:32:36 -0400589#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100590
591template <output_iterator<const char&> _OutIt, class... _Args>
Mark de Weverd4f31252021-09-04 13:26:58 +0200592_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
Mark de Wevercb50a052020-12-19 13:52:07 +0100593 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
Mark de Weverd4f31252021-09-04 13:26:58 +0200594 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
595 _VSTD::make_format_args(__args...));
Mark de Wevercb50a052020-12-19 13:52:07 +0100596}
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>
Mark de Weverd4f31252021-09-04 13:26:58 +0200600_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
Mark de Wevercb50a052020-12-19 13:52:07 +0100601 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
Mark de Weverd4f31252021-09-04 13:26:58 +0200602 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
603 _VSTD::make_wformat_args(__args...));
Mark de Wevercb50a052020-12-19 13:52:07 +0100604}
Louis Dionne89258142021-08-23 15:32:36 -0400605#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100606
Mark de Weverd4f31252021-09-04 13:26:58 +0200607_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
Mark de Wevercb50a052020-12-19 13:52:07 +0100608vformat(locale __loc, string_view __fmt, format_args __args) {
609 string __res;
610 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
611 __args);
612 return __res;
613}
614
Louis Dionne89258142021-08-23 15:32:36 -0400615#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverd4f31252021-09-04 13:26:58 +0200616_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
Mark de Wevercb50a052020-12-19 13:52:07 +0100617vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
618 wstring __res;
619 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
620 __args);
621 return __res;
622}
Louis Dionne89258142021-08-23 15:32:36 -0400623#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100624
625template <class... _Args>
Mark de Weverd4f31252021-09-04 13:26:58 +0200626_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
Mark de Wevercb50a052020-12-19 13:52:07 +0100627format(locale __loc, string_view __fmt, const _Args&... __args) {
628 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
629 _VSTD::make_format_args(__args...));
630}
631
Louis Dionne89258142021-08-23 15:32:36 -0400632#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100633template <class... _Args>
Mark de Weverd4f31252021-09-04 13:26:58 +0200634_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
Mark de Wevercb50a052020-12-19 13:52:07 +0100635format(locale __loc, wstring_view __fmt, const _Args&... __args) {
636 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
637 _VSTD::make_wformat_args(__args...));
638}
Louis Dionne89258142021-08-23 15:32:36 -0400639#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100640
641template <output_iterator<const char&> _OutIt, class... _Args>
642_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
643format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
644 string_view __fmt, const _Args&... __args) {
645 // TODO FMT Improve PoC: using std::string is inefficient.
646 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
647 _VSTD::make_format_args(__args...));
648 iter_difference_t<_OutIt> __s = __str.size();
649 iter_difference_t<_OutIt> __m =
650 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
651 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
652 return {_VSTD::move(__out_it), __s};
653}
654
Louis Dionne89258142021-08-23 15:32:36 -0400655#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100656template <output_iterator<const wchar_t&> _OutIt, class... _Args>
657_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
658format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
659 wstring_view __fmt, const _Args&... __args) {
660 // TODO FMT Improve PoC: using std::string is inefficient.
661 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
662 _VSTD::make_wformat_args(__args...));
663 iter_difference_t<_OutIt> __s = __str.size();
664 iter_difference_t<_OutIt> __m =
665 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
666 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
667 return {_VSTD::move(__out_it), __s};
668}
Louis Dionne89258142021-08-23 15:32:36 -0400669#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100670
671template <class... _Args>
672_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
673formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
674 // TODO FMT Improve PoC: using std::string is inefficient.
675 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
676 _VSTD::make_format_args(__args...))
677 .size();
678}
679
Louis Dionne89258142021-08-23 15:32:36 -0400680#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Wevercb50a052020-12-19 13:52:07 +0100681template <class... _Args>
682_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
683formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
684 // TODO FMT Improve PoC: using std::string is inefficient.
685 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
686 _VSTD::make_wformat_args(__args...))
687 .size();
688}
Louis Dionne89258142021-08-23 15:32:36 -0400689#endif
Mark de Wevercb50a052020-12-19 13:52:07 +0100690
Louis Dionneaf2c8142021-09-09 14:43:02 -0400691#endif // _LIBCPP_HAS_NO_LOCALIZATION
Mark de Wevercb50a052020-12-19 13:52:07 +0100692
Mark de Wevercba61372020-12-05 11:45:21 +0100693#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
694#endif //_LIBCPP_STD_VER > 17
695
696_LIBCPP_END_NAMESPACE_STD
697
Mark de Wevercb50a052020-12-19 13:52:07 +0100698_LIBCPP_POP_MACROS
699
Mark de Wever14151d22021-07-30 14:35:37 -0400700#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
701
Mark de Weverdf5fd832020-11-26 19:12:18 +0100702#endif // _LIBCPP_FORMAT