1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
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_FORMAT_FUNCTIONS
11 #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS
12
13 // TODO FMT This is added to fix Apple back-deployment.
14 #include <version>
15 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
16
17 #include <__algorithm/clamp.h>
18 #include <__availability>
19 #include <__concepts/convertible_to.h>
20 #include <__concepts/same_as.h>
21 #include <__config>
22 #include <__debug>
23 #include <__format/buffer.h>
24 #include <__format/format_arg.h>
25 #include <__format/format_arg_store.h>
26 #include <__format/format_args.h>
27 #include <__format/format_context.h>
28 #include <__format/format_error.h>
29 #include <__format/format_parse_context.h>
30 #include <__format/format_string.h>
31 #include <__format/format_to_n_result.h>
32 #include <__format/formatter.h>
33 #include <__format/formatter_bool.h>
34 #include <__format/formatter_char.h>
35 #include <__format/formatter_floating_point.h>
36 #include <__format/formatter_integer.h>
37 #include <__format/formatter_pointer.h>
38 #include <__format/formatter_string.h>
39 #include <__format/parser_std_format_spec.h>
40 #include <__iterator/back_insert_iterator.h>
41 #include <__iterator/concepts.h>
42 #include <__iterator/incrementable_traits.h>
43 #include <__iterator/readable_traits.h> // iter_value_t
44 #include <__variant/monostate.h>
45 #include <array>
46 #include <string>
47 #include <string_view>
48
49 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
50 #include <locale>
51 #endif
52
53 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
54 # pragma GCC system_header
55 #endif
56
57 _LIBCPP_BEGIN_NAMESPACE_STD
58
59 #if _LIBCPP_STD_VER >= 20
60
61 // TODO FMT Evaluate which templates should be external templates. This
62 // improves the efficiency of the header. However since the header is still
63 // under heavy development and not all classes are stable it makes no sense
64 // to do this optimization now.
65
66 using format_args = basic_format_args<format_context>;
67 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
68 using wformat_args = basic_format_args<wformat_context>;
69 #endif
70
71 template <class _Context = format_context, class... _Args>
make_format_args(_Args &&...__args)72 _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) {
73 return _VSTD::__format_arg_store<_Context, _Args...>(__args...);
74 }
75
76 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
77 template <class... _Args>
make_wformat_args(_Args &&...__args)78 _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) {
79 return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...);
80 }
81 #endif
82
83 namespace __format {
84
85 /// Helper class parse and handle argument.
86 ///
87 /// When parsing a handle which is not enabled the code is ill-formed.
88 /// This helper uses the parser of the appropriate formatter for the stored type.
89 template <class _CharT>
90 class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
91 public:
92 _LIBCPP_HIDE_FROM_ABI
__parse(basic_format_parse_context<_CharT> & __parse_ctx)93 constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); }
94
95 template <class _Tp>
__enable()96 _LIBCPP_HIDE_FROM_ABI constexpr void __enable() {
97 __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) {
98 formatter<_Tp, _CharT> __f;
99 __parse_ctx.advance_to(__f.parse(__parse_ctx));
100 };
101 }
102
103 // Before calling __parse the proper handler needs to be set with __enable.
104 // The default handler isn't a core constant expression.
__compile_time_handle()105 _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()
106 : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {}
107
108 private:
109 void (*__parse_)(basic_format_parse_context<_CharT>&);
110 };
111
112 // Dummy format_context only providing the parts used during constant
113 // validation of the basic_format_string.
114 template <class _CharT>
115 struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context {
116 public:
117 using char_type = _CharT;
118
__compile_time_basic_format_context__compile_time_basic_format_context119 _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(
120 const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)
121 : __args_(__args), __handles_(__handles), __size_(__size) {}
122
123 // During the compile-time validation nothing needs to be written.
124 // Therefore all operations of this iterator are a NOP.
125 struct iterator {
126 _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }
127 _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }
128 _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }
129 };
130
arg__compile_time_basic_format_context131 _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
132 if (__id >= __size_)
133 std::__throw_format_error("Argument index out of bounds");
134 return __args_[__id];
135 }
136
__handle__compile_time_basic_format_context137 _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {
138 if (__id >= __size_)
139 std::__throw_format_error("Argument index out of bounds");
140 return __handles_[__id];
141 }
142
out__compile_time_basic_format_context143 _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }
advance_to__compile_time_basic_format_context144 _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}
145
146 private:
147 const __arg_t* __args_;
148 const __compile_time_handle<_CharT>* __handles_;
149 size_t __size_;
150 };
151
152 // [format.string.std]/8
153 // If { arg-idopt } is used in a width or precision, the value of the
154 // corresponding formatting argument is used in its place. If the
155 // corresponding formatting argument is not of standard signed or unsigned
156 // integer type, or its value is negative for precision or non-positive for
157 // width, an exception of type format_error is thrown.
158 //
159 // _HasPrecision does the formatter have a precision?
160 template <class _CharT, class _Tp, bool _HasPrecision = false>
__compile_time_validate_argument(basic_format_parse_context<_CharT> & __parse_ctx,__compile_time_basic_format_context<_CharT> & __ctx)161 _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument(
162 basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) {
163 auto __validate_type = [](__arg_t __type) {
164 // LWG3720 originally allowed "signed or unsigned integer types", however
165 // the final version explicitly changed it to "*standard* signed or unsigned
166 // integer types". It's trivial to use 128-bit integrals in libc++'s
167 // implementation, but other implementations may not implement it.
168 // (Using a width or precision, that does not fit in 64-bits, sounds very
169 // unlikely in real world code.)
170 switch (__type) {
171 case __arg_t::__int:
172 case __arg_t::__long_long:
173 case __arg_t::__unsigned:
174 case __arg_t::__unsigned_long_long:
175 return;
176
177 default:
178 std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type");
179 }
180 };
181
182 formatter<_Tp, _CharT> __formatter;
183 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
184 if (__formatter.__parser_.__width_as_arg_)
185 __validate_type(__ctx.arg(__formatter.__parser_.__width_));
186
187 if constexpr (_HasPrecision)
188 if (__formatter.__parser_.__precision_as_arg_)
189 __validate_type(__ctx.arg(__formatter.__parser_.__precision_));
190 }
191
192 // This function is not user facing, so it can directly use the non-standard types of the "variant".
193 template <class _CharT>
__compile_time_visit_format_arg(basic_format_parse_context<_CharT> & __parse_ctx,__compile_time_basic_format_context<_CharT> & __ctx,__arg_t __type)194 _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx,
195 __compile_time_basic_format_context<_CharT>& __ctx,
196 __arg_t __type) {
197 switch (__type) {
198 case __arg_t::__none:
199 std::__throw_format_error("Invalid argument");
200 case __arg_t::__boolean:
201 return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);
202 case __arg_t::__char_type:
203 return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);
204 case __arg_t::__int:
205 return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);
206 case __arg_t::__long_long:
207 return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);
208 case __arg_t::__i128:
209 # ifndef _LIBCPP_HAS_NO_INT128
210 return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);
211 # else
212 std::__throw_format_error("Invalid argument");
213 # endif
214 return;
215 case __arg_t::__unsigned:
216 return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);
217 case __arg_t::__unsigned_long_long:
218 return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);
219 case __arg_t::__u128:
220 # ifndef _LIBCPP_HAS_NO_INT128
221 return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);
222 # else
223 std::__throw_format_error("Invalid argument");
224 # endif
225 return;
226 case __arg_t::__float:
227 return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);
228 case __arg_t::__double:
229 return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);
230 case __arg_t::__long_double:
231 return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);
232 case __arg_t::__const_char_type_ptr:
233 return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);
234 case __arg_t::__string_view:
235 return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);
236 case __arg_t::__ptr:
237 return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);
238 case __arg_t::__handle:
239 std::__throw_format_error("Handle should use __compile_time_validate_handle_argument");
240 }
241 std::__throw_format_error("Invalid argument");
242 }
243
244 template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx>
245 _LIBCPP_HIDE_FROM_ABI constexpr _Iterator
__handle_replacement_field(_Iterator __begin,_Iterator __end,_ParseCtx & __parse_ctx,_Ctx & __ctx)246 __handle_replacement_field(_Iterator __begin, _Iterator __end,
247 _ParseCtx& __parse_ctx, _Ctx& __ctx) {
248 using _CharT = iter_value_t<_Iterator>;
249 __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
250
251 bool __parse = *__r.__last == _CharT(':');
252 switch (*__r.__last) {
253 case _CharT(':'):
254 // The arg-id has a format-specifier, advance the input to the format-spec.
255 __parse_ctx.advance_to(__r.__last + 1);
256 break;
257 case _CharT('}'):
258 // The arg-id has no format-specifier.
259 __parse_ctx.advance_to(__r.__last);
260 break;
261 default:
262 std::__throw_format_error("The replacement field arg-id should terminate at a ':' or '}'");
263 }
264
265 if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
266 __arg_t __type = __ctx.arg(__r.__value);
267 if (__type == __arg_t::__none)
268 std::__throw_format_error("Argument index out of bounds");
269 else if (__type == __arg_t::__handle)
270 __ctx.__handle(__r.__value).__parse(__parse_ctx);
271 else if (__parse)
272 __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
273 } else
274 _VSTD::__visit_format_arg(
275 [&](auto __arg) {
276 if constexpr (same_as<decltype(__arg), monostate>)
277 std::__throw_format_error("Argument index out of bounds");
278 else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
279 __arg.format(__parse_ctx, __ctx);
280 else {
281 formatter<decltype(__arg), _CharT> __formatter;
282 if (__parse)
283 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
284 __ctx.advance_to(__formatter.format(__arg, __ctx));
285 }
286 },
287 __ctx.arg(__r.__value));
288
289 __begin = __parse_ctx.begin();
290 if (__begin == __end || *__begin != _CharT('}'))
291 std::__throw_format_error("The replacement field misses a terminating '}'");
292
293 return ++__begin;
294 }
295
296 template <class _ParseCtx, class _Ctx>
297 _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator
__vformat_to(_ParseCtx && __parse_ctx,_Ctx && __ctx)298 __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
299 using _CharT = typename _ParseCtx::char_type;
300 static_assert(same_as<typename _Ctx::char_type, _CharT>);
301
302 auto __begin = __parse_ctx.begin();
303 auto __end = __parse_ctx.end();
304 typename _Ctx::iterator __out_it = __ctx.out();
305 while (__begin != __end) {
306 switch (*__begin) {
307 case _CharT('{'):
308 ++__begin;
309 if (__begin == __end)
310 std::__throw_format_error("The format string terminates at a '{'");
311
312 if (*__begin != _CharT('{')) [[likely]] {
313 __ctx.advance_to(_VSTD::move(__out_it));
314 __begin =
315 __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
316 __out_it = __ctx.out();
317
318 // The output is written and __begin points to the next character. So
319 // start the next iteration.
320 continue;
321 }
322 // The string is an escape character.
323 break;
324
325 case _CharT('}'):
326 ++__begin;
327 if (__begin == __end || *__begin != _CharT('}'))
328 std::__throw_format_error("The format string contains an invalid escape sequence");
329
330 break;
331 }
332
333 // Copy the character to the output verbatim.
334 *__out_it++ = *__begin++;
335 }
336 return __out_it;
337 }
338
339 } // namespace __format
340
341 template <class _CharT, class... _Args>
342 struct _LIBCPP_TEMPLATE_VIS basic_format_string {
343 template <class _Tp>
344 requires convertible_to<const _Tp&, basic_string_view<_CharT>>
basic_format_stringbasic_format_string345 consteval basic_format_string(const _Tp& __str) : __str_{__str} {
346 __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
347 _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
348 }
349
getbasic_format_string350 _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept {
351 return __str_;
352 }
353
354 private:
355 basic_string_view<_CharT> __str_;
356
357 using _Context = __format::__compile_time_basic_format_context<_CharT>;
358
359 static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{
360 __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};
361
362 // TODO FMT remove this work-around when the AIX ICE has been resolved.
363 # if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400
364 template <class _Tp>
__get_handlebasic_format_string365 static constexpr __format::__compile_time_handle<_CharT> __get_handle() {
366 __format::__compile_time_handle<_CharT> __handle;
367 if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
368 __handle.template __enable<_Tp>();
369
370 return __handle;
371 }
372
373 static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{
374 __get_handle<_Args>()...};
375 # else
376 static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {
377 using _Tp = remove_cvref_t<_Args>;
378 __format::__compile_time_handle<_CharT> __handle;
379 if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
380 __handle.template __enable<_Tp>();
381
382 return __handle;
383 }()...};
384 # endif
385 };
386
387 template <class... _Args>
388 using format_string = basic_format_string<char, type_identity_t<_Args>...>;
389
390 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
391 template <class... _Args>
392 using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>;
393 #endif
394
395 template <class _OutIt, class _CharT, class _FormatOutIt>
requires(output_iterator<_OutIt,const _CharT &>)396 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
397 __vformat_to(
398 _OutIt __out_it, basic_string_view<_CharT> __fmt,
399 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
400 if constexpr (same_as<_OutIt, _FormatOutIt>)
401 return _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
402 _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
403 else {
404 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
405 _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
406 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
407 return _VSTD::move(__buffer).__out_it();
408 }
409 }
410
411 // The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
412 // https://reviews.llvm.org/D110499#inline-1180704
413 // TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
414 template <output_iterator<const char&> _OutIt>
415 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
vformat_to(_OutIt __out_it,string_view __fmt,format_args __args)416 vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
417 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
418 }
419
420 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
421 template <output_iterator<const wchar_t&> _OutIt>
422 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
vformat_to(_OutIt __out_it,wstring_view __fmt,wformat_args __args)423 vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
424 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
425 }
426 #endif
427
428 template <output_iterator<const char&> _OutIt, class... _Args>
429 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
format_to(_OutIt __out_it,format_string<_Args...> __fmt,_Args &&...__args)430 format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) {
431 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(),
432 _VSTD::make_format_args(__args...));
433 }
434
435 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
436 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
437 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
format_to(_OutIt __out_it,wformat_string<_Args...> __fmt,_Args &&...__args)438 format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {
439 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(),
440 _VSTD::make_wformat_args(__args...));
441 }
442 #endif
443
444 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
445 // fires too eagerly, see http://llvm.org/PR61563.
446 template <class = void>
447 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string
vformat(string_view __fmt,format_args __args)448 vformat(string_view __fmt, format_args __args) {
449 string __res;
450 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
451 return __res;
452 }
453
454 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
455 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
456 // fires too eagerly, see http://llvm.org/PR61563.
457 template <class = void>
458 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
vformat(wstring_view __fmt,wformat_args __args)459 vformat(wstring_view __fmt, wformat_args __args) {
460 wstring __res;
461 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
462 return __res;
463 }
464 #endif
465
466 template <class... _Args>
format(format_string<_Args...> __fmt,_Args &&...__args)467 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(format_string<_Args...> __fmt,
468 _Args&&... __args) {
469 return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...));
470 }
471
472 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
473 template <class... _Args>
474 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring
format(wformat_string<_Args...> __fmt,_Args &&...__args)475 format(wformat_string<_Args...> __fmt, _Args&&... __args) {
476 return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...));
477 }
478 #endif
479
480 template <class _Context, class _OutIt, class _CharT>
__vformat_to_n(_OutIt __out_it,iter_difference_t<_OutIt> __n,basic_string_view<_CharT> __fmt,basic_format_args<_Context> __args)481 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
482 basic_string_view<_CharT> __fmt,
483 basic_format_args<_Context> __args) {
484 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
485 _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
486 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
487 return _VSTD::move(__buffer).__result();
488 }
489
490 template <output_iterator<const char&> _OutIt, class... _Args>
491 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
format_to_n(_OutIt __out_it,iter_difference_t<_OutIt> __n,format_string<_Args...> __fmt,_Args &&...__args)492 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) {
493 return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...));
494 }
495
496 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
497 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
498 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
format_to_n(_OutIt __out_it,iter_difference_t<_OutIt> __n,wformat_string<_Args...> __fmt,_Args &&...__args)499 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt,
500 _Args&&... __args) {
501 return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...));
502 }
503 #endif
504
505 template <class _CharT>
__vformatted_size(basic_string_view<_CharT> __fmt,auto __args)506 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
507 __format::__formatted_size_buffer<_CharT> __buffer;
508 _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
509 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
510 return _VSTD::move(__buffer).__result();
511 }
512
513 template <class... _Args>
514 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
formatted_size(format_string<_Args...> __fmt,_Args &&...__args)515 formatted_size(format_string<_Args...> __fmt, _Args&&... __args) {
516 return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)});
517 }
518
519 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
520 template <class... _Args>
521 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
formatted_size(wformat_string<_Args...> __fmt,_Args &&...__args)522 formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) {
523 return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)});
524 }
525 #endif
526
527 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
528
529 template <class _OutIt, class _CharT, class _FormatOutIt>
requires(output_iterator<_OutIt,const _CharT &>)530 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
531 __vformat_to(
532 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
533 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
534 if constexpr (same_as<_OutIt, _FormatOutIt>)
535 return _VSTD::__format::__vformat_to(
536 basic_format_parse_context{__fmt, __args.__size()},
537 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, _VSTD::move(__loc)));
538 else {
539 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
540 _VSTD::__format::__vformat_to(
541 basic_format_parse_context{__fmt, __args.__size()},
542 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
543 return _VSTD::move(__buffer).__out_it();
544 }
545 }
546
547 template <output_iterator<const char&> _OutIt>
vformat_to(_OutIt __out_it,locale __loc,string_view __fmt,format_args __args)548 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(
549 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
550 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
551 __args);
552 }
553
554 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
555 template <output_iterator<const wchar_t&> _OutIt>
vformat_to(_OutIt __out_it,locale __loc,wstring_view __fmt,wformat_args __args)556 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(
557 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
558 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
559 __args);
560 }
561 #endif
562
563 template <output_iterator<const char&> _OutIt, class... _Args>
564 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
format_to(_OutIt __out_it,locale __loc,format_string<_Args...> __fmt,_Args &&...__args)565 format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
566 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(),
567 _VSTD::make_format_args(__args...));
568 }
569
570 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
571 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
572 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
format_to(_OutIt __out_it,locale __loc,wformat_string<_Args...> __fmt,_Args &&...__args)573 format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
574 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(),
575 _VSTD::make_wformat_args(__args...));
576 }
577 #endif
578
579 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
580 // fires too eagerly, see http://llvm.org/PR61563.
581 template <class = void>
582 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string
vformat(locale __loc,string_view __fmt,format_args __args)583 vformat(locale __loc, string_view __fmt, format_args __args) {
584 string __res;
585 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
586 __args);
587 return __res;
588 }
589
590 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
591 // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
592 // fires too eagerly, see http://llvm.org/PR61563.
593 template <class = void>
594 _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
vformat(locale __loc,wstring_view __fmt,wformat_args __args)595 vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
596 wstring __res;
597 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
598 __args);
599 return __res;
600 }
601 #endif
602
603 template <class... _Args>
format(locale __loc,format_string<_Args...> __fmt,_Args &&...__args)604 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(locale __loc,
605 format_string<_Args...> __fmt,
606 _Args&&... __args) {
607 return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(),
608 _VSTD::make_format_args(__args...));
609 }
610
611 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
612 template <class... _Args>
613 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring
format(locale __loc,wformat_string<_Args...> __fmt,_Args &&...__args)614 format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
615 return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(),
616 _VSTD::make_wformat_args(__args...));
617 }
618 #endif
619
620 template <class _Context, class _OutIt, class _CharT>
__vformat_to_n(_OutIt __out_it,iter_difference_t<_OutIt> __n,locale __loc,basic_string_view<_CharT> __fmt,basic_format_args<_Context> __args)621 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
622 locale __loc, basic_string_view<_CharT> __fmt,
623 basic_format_args<_Context> __args) {
624 __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
625 _VSTD::__format::__vformat_to(
626 basic_format_parse_context{__fmt, __args.__size()},
627 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
628 return _VSTD::move(__buffer).__result();
629 }
630
631 template <output_iterator<const char&> _OutIt, class... _Args>
632 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
format_to_n(_OutIt __out_it,iter_difference_t<_OutIt> __n,locale __loc,format_string<_Args...> __fmt,_Args &&...__args)633 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt,
634 _Args&&... __args) {
635 return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(),
636 _VSTD::make_format_args(__args...));
637 }
638
639 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
640 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
641 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
format_to_n(_OutIt __out_it,iter_difference_t<_OutIt> __n,locale __loc,wformat_string<_Args...> __fmt,_Args &&...__args)642 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt,
643 _Args&&... __args) {
644 return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(),
645 _VSTD::make_wformat_args(__args...));
646 }
647 #endif
648
649 template <class _CharT>
__vformatted_size(locale __loc,basic_string_view<_CharT> __fmt,auto __args)650 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
651 __format::__formatted_size_buffer<_CharT> __buffer;
652 _VSTD::__format::__vformat_to(
653 basic_format_parse_context{__fmt, __args.__size()},
654 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
655 return _VSTD::move(__buffer).__result();
656 }
657
658 template <class... _Args>
659 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
formatted_size(locale __loc,format_string<_Args...> __fmt,_Args &&...__args)660 formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
661 return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)});
662 }
663
664 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
665 template <class... _Args>
666 _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
formatted_size(locale __loc,wformat_string<_Args...> __fmt,_Args &&...__args)667 formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
668 return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)});
669 }
670 #endif
671
672 #endif // _LIBCPP_HAS_NO_LOCALIZATION
673
674
675 #endif //_LIBCPP_STD_VER >= 20
676
677 _LIBCPP_END_NAMESPACE_STD
678
679 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
680
681 #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS
682