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