]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/libcxx/include/format
Merge llvm-project main llvmorg-14-init-10186-gff7f2cfa959b
[FreeBSD/FreeBSD.git] / contrib / llvm-project / libcxx / include / format
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
11 #define _LIBCPP_FORMAT
12
13 /*
14
15 namespace std {
16   // [format.context], class template basic_format_context
17   template<class Out, class charT>
18   class basic_format_context {
19     basic_format_args<basic_format_context> args_;      // exposition only
20     Out out_;                                           // exposition only
21
22   public:
23     using iterator = Out;
24     using char_type = charT;
25     template<class T> using formatter_type = formatter<T, charT>;
26
27     basic_format_arg<basic_format_context> arg(size_t id) const;
28     std::locale locale();
29
30     iterator out();
31     void advance_to(iterator it);
32   };
33   using format_context = basic_format_context<unspecified, char>;
34   using wformat_context = basic_format_context<unspecified, wchar_t>;
35
36   // [format.args], class template basic_format_args
37   template<class Context>
38   class basic_format_args {
39     size_t size_;                               // exposition only
40     const basic_format_arg<Context>* data_;     // exposition only
41
42   public:
43     basic_format_args() noexcept;
44
45     template<class... Args>
46       basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
47
48     basic_format_arg<Context> get(size_t i) const noexcept;
49   };
50   using format_args = basic_format_args<format_context>;
51   using wformat_args = basic_format_args<wformat_context>;
52
53
54   template<class Out, class charT>
55     using format_args_t = basic_format_args<basic_format_context<Out, charT>>;
56
57   // [format.functions], formatting functions
58   template<class... Args>
59     string format(string_view fmt, const Args&... args);
60   template<class... Args>
61     wstring format(wstring_view fmt, const Args&... args);
62   template<class... Args>
63     string format(const locale& loc, string_view fmt, const Args&... args);
64   template<class... Args>
65     wstring format(const locale& loc, wstring_view fmt, const Args&... args);
66
67   string vformat(string_view fmt, format_args args);
68   wstring vformat(wstring_view fmt, wformat_args args);
69   string vformat(const locale& loc, string_view fmt, format_args args);
70   wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
71
72   template<class Out, class... Args>
73     Out format_to(Out out, string_view fmt, const Args&... args);
74   template<class Out, class... Args>
75     Out format_to(Out out, wstring_view fmt, const Args&... args);
76   template<class Out, class... Args>
77     Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
78   template<class Out, class... Args>
79     Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
80
81   template<class Out>
82     Out vformat_to(Out out, string_view fmt,
83                    format_args_t<type_identity_t<Out>, char> args);
84   template<class Out>
85     Out vformat_to(Out out, wstring_view fmt,
86                    format_args_t<type_identity_t<Out>, wchar_t> args);
87   template<class Out>
88     Out vformat_to(Out out, const locale& loc, string_view fmt,
89                    format_args_t<type_identity_t<Out>, char> args);
90   template<class Out>
91     Out vformat_to(Out out, const locale& loc, wstring_view fmt,
92                    format_args_t<type_identity_t<Out>, wchar_t> args);
93
94   template<class Out> struct format_to_n_result {
95     Out out;
96     iter_difference_t<Out> size;
97   };
98
99  template<class Out, class... Args>
100     format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
101                                         string_view fmt, const Args&... args);
102   template<class Out, class... Args>
103     format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
104                                         wstring_view fmt, const Args&... args);
105   template<class Out, class... Args>
106     format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
107                                         const locale& loc, string_view fmt,
108                                         const Args&... args);
109   template<class Out, class... Args>
110     format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
111                                         const locale& loc, wstring_view fmt,
112                                         const Args&... args);
113
114   template<class... Args>
115     size_t formatted_size(string_view fmt, const Args&... args);
116   template<class... Args>
117     size_t formatted_size(wstring_view fmt, const Args&... args);
118   template<class... Args>
119     size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
120   template<class... Args>
121     size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
122
123   // [format.formatter], formatter
124   template<> struct formatter<char, char>;
125   template<> struct formatter<char, wchar_t>;
126   template<> struct formatter<wchar_t, wchar_t>;
127
128   template<> struct formatter<charT*, charT>;
129   template<> struct formatter<const charT*, charT>;
130   template<size_t N> struct formatter<const charT[N], charT>;
131   template<class traits, class Allocator>
132     struct formatter<basic_string<charT, traits, Allocator>, charT>;
133   template<class traits>
134     struct formatter<basic_string_view<charT, traits>, charT>;
135
136   // [format.parse.ctx], class template basic_format_parse_context
137   template<class charT>
138   class basic_format_parse_context {
139   public:
140     using char_type = charT;
141     using const_iterator = typename basic_string_view<charT>::const_iterator;
142     using iterator = const_iterator;
143
144   private:
145     iterator begin_;                                    // exposition only
146     iterator end_;                                      // exposition only
147     enum indexing { unknown, manual, automatic };       // exposition only
148     indexing indexing_;                                 // exposition only
149     size_t next_arg_id_;                                // exposition only
150     size_t num_args_;                                   // exposition only
151
152   public:
153     constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
154                                                   size_t num_args = 0) noexcept;
155     basic_format_parse_context(const basic_format_parse_context&) = delete;
156     basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
157
158     constexpr const_iterator begin() const noexcept;
159     constexpr const_iterator end() const noexcept;
160     constexpr void advance_to(const_iterator it);
161
162     constexpr size_t next_arg_id();
163     constexpr void check_arg_id(size_t id);
164   };
165   using format_parse_context = basic_format_parse_context<char>;
166   using wformat_parse_context = basic_format_parse_context<wchar_t>;
167
168   // [format.arguments], arguments
169   // [format.arg], class template basic_format_arg
170   template<class Context>
171   class basic_format_arg {
172   public:
173     class handle;
174
175   private:
176     using char_type = typename Context::char_type;                              // exposition only
177
178     variant<monostate, bool, char_type,
179             int, unsigned int, long long int, unsigned long long int,
180             float, double, long double,
181             const char_type*, basic_string_view<char_type>,
182             const void*, handle> value;                                         // exposition only
183
184     template<class T> explicit basic_format_arg(const T& v) noexcept;           // exposition only
185     explicit basic_format_arg(float n) noexcept;                                // exposition only
186     explicit basic_format_arg(double n) noexcept;                               // exposition only
187     explicit basic_format_arg(long double n) noexcept;                          // exposition only
188     explicit basic_format_arg(const char_type* s);                              // exposition only
189
190     template<class traits>
191       explicit basic_format_arg(
192         basic_string_view<char_type, traits> s) noexcept;                       // exposition only
193
194     template<class traits, class Allocator>
195       explicit basic_format_arg(
196         const basic_string<char_type, traits, Allocator>& s) noexcept;          // exposition only
197
198     explicit basic_format_arg(nullptr_t) noexcept;                              // exposition only
199
200     template<class T>
201       explicit basic_format_arg(const T* p) noexcept;                           // exposition only
202
203   public:
204     basic_format_arg() noexcept;
205
206     explicit operator bool() const noexcept;
207   };
208
209   template<class Visitor, class Context>
210     see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
211
212   // [format.arg.store], class template format-arg-store
213   template<class Context, class... Args>
214   struct format-arg-store {      // exposition only
215     array<basic_format_arg<Context>, sizeof...(Args)> args;
216   };
217
218   template<class Context = format_context, class... Args>
219     format-arg-store<Context, Args...>
220       make_format_args(const Args&... args);
221   template<class... Args>
222     format-arg-store<wformat_context, Args...>
223       make_wformat_args(const Args&... args);
224
225   // [format.error], class format_error
226   class format_error : public runtime_error {
227   public:
228     explicit format_error(const string& what_arg);
229     explicit format_error(const char* what_arg);
230   };
231
232   // [format.parse.ctx], class template basic_format_parse_context
233   template<class charT>
234   class basic_format_parse_context {
235   public:
236     using char_type = charT;
237     using const_iterator = typename basic_string_view<charT>::const_iterator;
238     using iterator = const_iterator;
239
240   private:
241     iterator begin_;                                    // exposition only
242     iterator end_;                                      // exposition only
243     enum indexing { unknown, manual, automatic };       // exposition only
244     indexing indexing_;                                 // exposition only
245     size_t next_arg_id_;                                // exposition only
246     size_t num_args_;                                   // exposition only
247
248   public:
249     constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
250                                                   size_t num_args = 0) noexcept;
251     basic_format_parse_context(const basic_format_parse_context&) = delete;
252     basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
253
254     constexpr const_iterator begin() const noexcept;
255     constexpr const_iterator end() const noexcept;
256     constexpr void advance_to(const_iterator it);
257
258     constexpr size_t next_arg_id();
259     constexpr void check_arg_id(size_t id);
260   };
261   using format_parse_context = basic_format_parse_context<char>;
262   using wformat_parse_context = basic_format_parse_context<wchar_t>;
263 }
264
265 */
266
267 // Make sure all feature-test macros are available.
268 #include <version>
269 // Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
270 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
271
272 #include <__config>
273 #include <__debug>
274 #include <__format/format_arg.h>
275 #include <__format/format_args.h>
276 #include <__format/format_context.h>
277 #include <__format/format_error.h>
278 #include <__format/format_fwd.h>
279 #include <__format/format_parse_context.h>
280 #include <__format/format_string.h>
281 #include <__format/format_to_n_result.h>
282 #include <__format/formatter.h>
283 #include <__format/formatter_bool.h>
284 #include <__format/formatter_char.h>
285 #include <__format/formatter_integer.h>
286 #include <__format/formatter_string.h>
287 #include <__format/parser_std_format_spec.h>
288 #include <__variant/monostate.h>
289 #include <array>
290 #include <concepts>
291 #include <string>
292 #include <string_view>
293 #include <type_traits>
294
295 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
296 #include <locale>
297 #endif
298
299 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
300 #pragma GCC system_header
301 #endif
302
303 _LIBCPP_PUSH_MACROS
304 #include <__undef_macros>
305
306 _LIBCPP_BEGIN_NAMESPACE_STD
307
308 #if _LIBCPP_STD_VER > 17
309
310 // TODO FMT Remove this once we require compilers with proper C++20 support.
311 // If the compiler has no concepts support, the format header will be disabled.
312 // Without concepts support enable_if needs to be used and that too much effort
313 // to support compilers with partial C++20 support.
314 #if !defined(_LIBCPP_HAS_NO_CONCEPTS)
315
316 // TODO FMT Move the implementation in this file to its own granular headers.
317
318 // TODO FMT Evaluate which templates should be external templates. This
319 // improves the efficiency of the header. However since the header is still
320 // under heavy development and not all classes are stable it makes no sense
321 // to do this optimization now.
322
323 using format_args = basic_format_args<format_context>;
324 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
325 using wformat_args = basic_format_args<wformat_context>;
326 #endif
327
328 template <class _OutIt, class _CharT>
329 using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
330
331 template <class _Context, class... _Args>
332 struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
333   // TODO FMT Use a built-in array.
334   array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
335 };
336
337 template <class _Context = format_context, class... _Args>
338 _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
339 make_format_args(const _Args&... __args) {
340   return {basic_format_arg<_Context>(__args)...};
341 }
342
343 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
344 template <class... _Args>
345 _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
346 make_wformat_args(const _Args&... __args) {
347   return _VSTD::make_format_args<wformat_context>(__args...);
348 }
349 #endif
350
351 namespace __format {
352
353 template <class _CharT, class _ParseCtx, class _Ctx>
354 _LIBCPP_HIDE_FROM_ABI const _CharT*
355 __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
356                            _ParseCtx& __parse_ctx, _Ctx& __ctx) {
357   __format::__parse_number_result __r =
358       __format::__parse_arg_id(__begin, __end, __parse_ctx);
359
360   switch (*__r.__ptr) {
361   case _CharT(':'):
362     // The arg-id has a format-specifier, advance the input to the format-spec.
363     __parse_ctx.advance_to(__r.__ptr + 1);
364     break;
365   case _CharT('}'):
366     // The arg-id has no format-specifier.
367     __parse_ctx.advance_to(__r.__ptr);
368     break;
369   default:
370     __throw_format_error(
371         "The replacement field arg-id should terminate at a ':' or '}'");
372   }
373
374   _VSTD::visit_format_arg(
375       [&](auto __arg) {
376         if constexpr (same_as<decltype(__arg), monostate>)
377           __throw_format_error("Argument index out of bounds");
378         else {
379           formatter<decltype(__arg), _CharT> __formatter;
380           __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
381           __ctx.advance_to(__formatter.format(__arg, __ctx));
382         }
383       },
384       __ctx.arg(__r.__value));
385
386   __begin = __parse_ctx.begin();
387   if (__begin == __end || *__begin != _CharT('}'))
388     __throw_format_error("The replacement field misses a terminating '}'");
389
390   return ++__begin;
391 }
392
393 template <class _ParseCtx, class _Ctx>
394 _LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
395 __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
396   using _CharT = typename _ParseCtx::char_type;
397   static_assert(same_as<typename _Ctx::char_type, _CharT>);
398
399   const _CharT* __begin = __parse_ctx.begin();
400   const _CharT* __end = __parse_ctx.end();
401   typename _Ctx::iterator __out_it = __ctx.out();
402   while (__begin != __end) {
403     switch (*__begin) {
404     case _CharT('{'):
405       ++__begin;
406       if (__begin == __end)
407         __throw_format_error("The format string terminates at a '{'");
408
409       if (*__begin != _CharT('{')) [[likely]] {
410         __ctx.advance_to(_VSTD::move(__out_it));
411         __begin =
412             __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
413         __out_it = __ctx.out();
414
415         // The output is written and __begin points to the next character. So
416         // start the next iteration.
417         continue;
418       }
419       // The string is an escape character.
420       break;
421
422     case _CharT('}'):
423       ++__begin;
424       if (__begin == __end || *__begin != _CharT('}'))
425         __throw_format_error(
426             "The format string contains an invalid escape sequence");
427
428       break;
429     }
430
431     // Copy the character to the output verbatim.
432     *__out_it++ = *__begin++;
433   }
434   return __out_it;
435 }
436
437 } // namespace __format
438
439 template <class _OutIt, class _CharT>
440 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
441     __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt,
442                  format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
443   return __format::__vformat_to(
444       basic_format_parse_context{__fmt, __args.__size()},
445       _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
446 }
447
448 template <output_iterator<const char&> _OutIt>
449 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
450 vformat_to(_OutIt __out_it, string_view __fmt,
451            format_args_t<type_identity_t<_OutIt>, char> __args) {
452   return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
453 }
454
455 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
456 template <output_iterator<const wchar_t&> _OutIt>
457 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
458 vformat_to(_OutIt __out_it, wstring_view __fmt,
459            format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
460   return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
461 }
462 #endif
463
464 template <output_iterator<const char&> _OutIt, class... _Args>
465 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
466 format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
467   return _VSTD::vformat_to(
468       _VSTD::move(__out_it), __fmt,
469       _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
470 }
471
472 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
473 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
474 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
475 format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
476   return _VSTD::vformat_to(
477       _VSTD::move(__out_it), __fmt,
478       _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
479           __args...));
480 }
481 #endif
482
483 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
484 vformat(string_view __fmt, format_args __args) {
485   string __res;
486   _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
487   return __res;
488 }
489
490 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
491 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
492 vformat(wstring_view __fmt, wformat_args __args) {
493   wstring __res;
494   _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
495   return __res;
496 }
497 #endif
498
499 template <class... _Args>
500 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
501 format(string_view __fmt, const _Args&... __args) {
502   return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
503 }
504
505 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
506 template <class... _Args>
507 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
508 format(wstring_view __fmt, const _Args&... __args) {
509   return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
510 }
511 #endif
512
513 template <output_iterator<const char&> _OutIt, class... _Args>
514 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
515 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
516             const _Args&... __args) {
517   // TODO FMT Improve PoC: using std::string is inefficient.
518   string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
519   iter_difference_t<_OutIt> __s = __str.size();
520   iter_difference_t<_OutIt> __m =
521       _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
522   __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
523   return {_VSTD::move(__out_it), __s};
524 }
525
526 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
527 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
528 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
529 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
530             const _Args&... __args) {
531   // TODO FMT Improve PoC: using std::string is inefficient.
532   wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
533   iter_difference_t<_OutIt> __s = __str.size();
534   iter_difference_t<_OutIt> __m =
535       _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
536   __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
537   return {_VSTD::move(__out_it), __s};
538 }
539 #endif
540
541 template <class... _Args>
542 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
543 formatted_size(string_view __fmt, const _Args&... __args) {
544   // TODO FMT Improve PoC: using std::string is inefficient.
545   return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
546 }
547
548 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
549 template <class... _Args>
550 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
551 formatted_size(wstring_view __fmt, const _Args&... __args) {
552   // TODO FMT Improve PoC: using std::string is inefficient.
553   return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
554 }
555 #endif
556
557 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
558
559 template <class _OutIt, class _CharT>
560 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
561     __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
562                  format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
563   return __format::__vformat_to(
564       basic_format_parse_context{__fmt, __args.__size()},
565       _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
566                                      _VSTD::move(__loc)));
567 }
568
569 template <output_iterator<const char&> _OutIt>
570 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
571 vformat_to(_OutIt __out_it, locale __loc, string_view __fmt,
572            format_args_t<type_identity_t<_OutIt>, char> __args) {
573   return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
574                              __args);
575 }
576
577 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
578 template <output_iterator<const wchar_t&> _OutIt>
579 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
580 vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt,
581            format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
582   return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
583                              __args);
584 }
585 #endif
586
587 template <output_iterator<const char&> _OutIt, class... _Args>
588 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
589     _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
590   return _VSTD::vformat_to(
591       _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
592       _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
593 }
594
595 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
596 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
597 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
598     _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
599   return _VSTD::vformat_to(
600       _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
601       _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
602           __args...));
603 }
604 #endif
605
606 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
607 vformat(locale __loc, string_view __fmt, format_args __args) {
608   string __res;
609   _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
610                     __args);
611   return __res;
612 }
613
614 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
615 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
616 vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
617   wstring __res;
618   _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
619                     __args);
620   return __res;
621 }
622 #endif
623
624 template <class... _Args>
625 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
626 format(locale __loc, string_view __fmt, const _Args&... __args) {
627   return _VSTD::vformat(_VSTD::move(__loc), __fmt,
628                         _VSTD::make_format_args(__args...));
629 }
630
631 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
632 template <class... _Args>
633 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
634 format(locale __loc, wstring_view __fmt, const _Args&... __args) {
635   return _VSTD::vformat(_VSTD::move(__loc), __fmt,
636                         _VSTD::make_wformat_args(__args...));
637 }
638 #endif
639
640 template <output_iterator<const char&> _OutIt, class... _Args>
641 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
642 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
643             string_view __fmt, const _Args&... __args) {
644   // TODO FMT Improve PoC: using std::string is inefficient.
645   string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
646                                 _VSTD::make_format_args(__args...));
647   iter_difference_t<_OutIt> __s = __str.size();
648   iter_difference_t<_OutIt> __m =
649       _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
650   __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
651   return {_VSTD::move(__out_it), __s};
652 }
653
654 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
655 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
656 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
657 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
658             wstring_view __fmt, const _Args&... __args) {
659   // TODO FMT Improve PoC: using std::string is inefficient.
660   wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
661                                  _VSTD::make_wformat_args(__args...));
662   iter_difference_t<_OutIt> __s = __str.size();
663   iter_difference_t<_OutIt> __m =
664       _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
665   __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
666   return {_VSTD::move(__out_it), __s};
667 }
668 #endif
669
670 template <class... _Args>
671 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
672 formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
673   // TODO FMT Improve PoC: using std::string is inefficient.
674   return _VSTD::vformat(_VSTD::move(__loc), __fmt,
675                         _VSTD::make_format_args(__args...))
676       .size();
677 }
678
679 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
680 template <class... _Args>
681 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
682 formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
683   // TODO FMT Improve PoC: using std::string is inefficient.
684   return _VSTD::vformat(_VSTD::move(__loc), __fmt,
685                         _VSTD::make_wformat_args(__args...))
686       .size();
687 }
688 #endif
689
690 #endif // _LIBCPP_HAS_NO_LOCALIZATION
691
692 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
693 #endif //_LIBCPP_STD_VER > 17
694
695 _LIBCPP_END_NAMESPACE_STD
696
697 _LIBCPP_POP_MACROS
698
699 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
700
701 #endif // _LIBCPP_FORMAT