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 15namespace std { 16 // [format.context], class template basic_format_context 17 template<class Out, class charT> class basic_format_context; 18 using format_context = basic_format_context<unspecified, char>; 19 using wformat_context = basic_format_context<unspecified, wchar_t>; 20 21 // [format.args], class template basic_format_args 22 template<class Context> class basic_format_args; 23 using format_args = basic_format_args<format_context>; 24 using wformat_args = basic_format_args<wformat_context>; 25 26 // [format.functions], formatting functions 27 template<class... Args> 28 string format(string_view fmt, const Args&... args); 29 template<class... Args> 30 wstring format(wstring_view fmt, const Args&... args); 31 template<class... Args> 32 string format(const locale& loc, string_view fmt, const Args&... args); 33 template<class... Args> 34 wstring format(const locale& loc, wstring_view fmt, const Args&... args); 35 36 string vformat(string_view fmt, format_args args); 37 wstring vformat(wstring_view fmt, wformat_args args); 38 string vformat(const locale& loc, string_view fmt, format_args args); 39 wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); 40 41 template<class Out, class... Args> 42 Out format_to(Out out, string_view fmt, const Args&... args); 43 template<class Out, class... Args> 44 Out format_to(Out out, wstring_view fmt, const Args&... args); 45 template<class Out, class... Args> 46 Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args); 47 template<class Out, class... Args> 48 Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args); 49 50 template<class Out> 51 Out vformat_to(Out out, string_view fmt, format_args args); 52 template<class Out> 53 Out vformat_to(Out out, wstring_view fmt, wformat_args args); 54 template<class Out> 55 Out vformat_to(Out out, const locale& loc, string_view fmt, 56 format_args char> args); 57 template<class Out> 58 Out vformat_to(Out out, const locale& loc, wstring_view fmt, 59 wformat_args args); 60 61 template<class Out> struct format_to_n_result { 62 Out out; 63 iter_difference_t<Out> size; 64 }; 65 template<class Out, class... Args> 66 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 67 string_view fmt, const Args&... args); 68 template<class Out, class... Args> 69 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 70 wstring_view fmt, const Args&... args); 71 template<class Out, class... Args> 72 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 73 const locale& loc, string_view fmt, 74 const Args&... args); 75 template<class Out, class... Args> 76 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 77 const locale& loc, wstring_view fmt, 78 const Args&... args); 79 80 template<class... Args> 81 size_t formatted_size(string_view fmt, const Args&... args); 82 template<class... Args> 83 size_t formatted_size(wstring_view fmt, const Args&... args); 84 template<class... Args> 85 size_t formatted_size(const locale& loc, string_view fmt, const Args&... args); 86 template<class... Args> 87 size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args); 88 89 // [format.formatter], formatter 90 template<class T, class charT = char> struct formatter; 91 92 // [format.parse.ctx], class template basic_format_parse_context 93 template<class charT> class basic_format_parse_context; 94 using format_parse_context = basic_format_parse_context<char>; 95 using wformat_parse_context = basic_format_parse_context<wchar_t>; 96 97 // [format.arguments], arguments 98 // [format.arg], class template basic_format_arg 99 template<class Context> class basic_format_arg; 100 101 template<class Visitor, class Context> 102 see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); 103 104 // [format.arg.store], class template format-arg-store 105 template<class Context, class... Args> struct format-arg-store; // exposition only 106 107 template<class Context = format_context, class... Args> 108 format-arg-store<Context, Args...> 109 make_format_args(const Args&... args); 110 template<class... Args> 111 format-arg-store<wformat_context, Args...> 112 make_wformat_args(const Args&... args); 113 114 // [format.error], class format_error 115 class format_error; 116} 117 118*/ 119 120// Make sure all feature-test macros are available. 121#include <version> 122// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES. 123#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 124 125#include <__algorithm/clamp.h> 126#include <__config> 127#include <__debug> 128#include <__format/buffer.h> 129#include <__format/format_arg.h> 130#include <__format/format_args.h> 131#include <__format/format_context.h> 132#include <__format/format_error.h> 133#include <__format/format_fwd.h> 134#include <__format/format_parse_context.h> 135#include <__format/format_string.h> 136#include <__format/format_to_n_result.h> 137#include <__format/formatter.h> 138#include <__format/formatter_bool.h> 139#include <__format/formatter_char.h> 140#include <__format/formatter_floating_point.h> 141#include <__format/formatter_integer.h> 142#include <__format/formatter_pointer.h> 143#include <__format/formatter_string.h> 144#include <__format/parser_std_format_spec.h> 145#include <__variant/monostate.h> 146#include <array> 147#include <concepts> 148#include <string> 149#include <string_view> 150#include <type_traits> 151 152#ifndef _LIBCPP_HAS_NO_LOCALIZATION 153#include <locale> 154#endif 155 156#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 157# pragma GCC system_header 158#endif 159 160_LIBCPP_BEGIN_NAMESPACE_STD 161 162#if _LIBCPP_STD_VER > 17 163 164// TODO FMT Move the implementation in this file to its own granular headers. 165 166// TODO FMT Evaluate which templates should be external templates. This 167// improves the efficiency of the header. However since the header is still 168// under heavy development and not all classes are stable it makes no sense 169// to do this optimization now. 170 171using format_args = basic_format_args<format_context>; 172#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 173using wformat_args = basic_format_args<wformat_context>; 174#endif 175 176template <class _Context, class... _Args> 177struct _LIBCPP_TEMPLATE_VIS __format_arg_store { 178 // TODO FMT Use a built-in array. 179 array<basic_format_arg<_Context>, sizeof...(_Args)> __args; 180}; 181 182template <class _Context = format_context, class... _Args> 183_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> 184make_format_args(const _Args&... __args) { 185 return {basic_format_arg<_Context>(__args)...}; 186} 187 188#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 189template <class... _Args> 190_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> 191make_wformat_args(const _Args&... __args) { 192 return _VSTD::make_format_args<wformat_context>(__args...); 193} 194#endif 195 196namespace __format { 197 198template <class _CharT, class _ParseCtx, class _Ctx> 199_LIBCPP_HIDE_FROM_ABI const _CharT* 200__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 201 _ParseCtx& __parse_ctx, _Ctx& __ctx) { 202 __format::__parse_number_result __r = 203 __format::__parse_arg_id(__begin, __end, __parse_ctx); 204 205 switch (*__r.__ptr) { 206 case _CharT(':'): 207 // The arg-id has a format-specifier, advance the input to the format-spec. 208 __parse_ctx.advance_to(__r.__ptr + 1); 209 break; 210 case _CharT('}'): 211 // The arg-id has no format-specifier. 212 __parse_ctx.advance_to(__r.__ptr); 213 break; 214 default: 215 __throw_format_error( 216 "The replacement field arg-id should terminate at a ':' or '}'"); 217 } 218 219 _VSTD::visit_format_arg( 220 [&](auto __arg) { 221 if constexpr (same_as<decltype(__arg), monostate>) 222 __throw_format_error("Argument index out of bounds"); 223 else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 224 __arg.format(__parse_ctx, __ctx); 225 else { 226 formatter<decltype(__arg), _CharT> __formatter; 227 __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 228 __ctx.advance_to(__formatter.format(__arg, __ctx)); 229 } 230 }, 231 __ctx.arg(__r.__value)); 232 233 __begin = __parse_ctx.begin(); 234 if (__begin == __end || *__begin != _CharT('}')) 235 __throw_format_error("The replacement field misses a terminating '}'"); 236 237 return ++__begin; 238} 239 240template <class _ParseCtx, class _Ctx> 241_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator 242__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 243 using _CharT = typename _ParseCtx::char_type; 244 static_assert(same_as<typename _Ctx::char_type, _CharT>); 245 246 const _CharT* __begin = __parse_ctx.begin(); 247 const _CharT* __end = __parse_ctx.end(); 248 typename _Ctx::iterator __out_it = __ctx.out(); 249 while (__begin != __end) { 250 switch (*__begin) { 251 case _CharT('{'): 252 ++__begin; 253 if (__begin == __end) 254 __throw_format_error("The format string terminates at a '{'"); 255 256 if (*__begin != _CharT('{')) [[likely]] { 257 __ctx.advance_to(_VSTD::move(__out_it)); 258 __begin = 259 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 260 __out_it = __ctx.out(); 261 262 // The output is written and __begin points to the next character. So 263 // start the next iteration. 264 continue; 265 } 266 // The string is an escape character. 267 break; 268 269 case _CharT('}'): 270 ++__begin; 271 if (__begin == __end || *__begin != _CharT('}')) 272 __throw_format_error( 273 "The format string contains an invalid escape sequence"); 274 275 break; 276 } 277 278 // Copy the character to the output verbatim. 279 *__out_it++ = *__begin++; 280 } 281 return __out_it; 282} 283 284} // namespace __format 285 286template <class _OutIt, class _CharT, class _FormatOutIt> 287requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 288 __vformat_to( 289 _OutIt __out_it, basic_string_view<_CharT> __fmt, 290 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 291 if constexpr (same_as<_OutIt, _FormatOutIt>) 292 return _VSTD::__format::__vformat_to( 293 basic_format_parse_context{__fmt, __args.__size()}, 294 _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 295 else { 296 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 297 _VSTD::__format::__vformat_to( 298 basic_format_parse_context{__fmt, __args.__size()}, 299 _VSTD::__format_context_create(__buffer.make_output_iterator(), 300 __args)); 301 return _VSTD::move(__buffer).out(); 302 } 303} 304 305template <output_iterator<const char&> _OutIt> 306_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 307vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 308 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 309} 310 311#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 312template <output_iterator<const wchar_t&> _OutIt> 313_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 314vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 315 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 316} 317#endif 318 319template <output_iterator<const char&> _OutIt, class... _Args> 320_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 321format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) { 322 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 323 _VSTD::make_format_args(__args...)); 324} 325 326#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 327template <output_iterator<const wchar_t&> _OutIt, class... _Args> 328_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 329format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) { 330 return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt, 331 _VSTD::make_wformat_args(__args...)); 332} 333#endif 334 335_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 336vformat(string_view __fmt, format_args __args) { 337 string __res; 338 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 339 return __res; 340} 341 342#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 343_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 344vformat(wstring_view __fmt, wformat_args __args) { 345 wstring __res; 346 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 347 return __res; 348} 349#endif 350 351template <class... _Args> 352_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 353format(string_view __fmt, const _Args&... __args) { 354 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 355} 356 357#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 358template <class... _Args> 359_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 360format(wstring_view __fmt, const _Args&... __args) { 361 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 362} 363#endif 364 365template <output_iterator<const char&> _OutIt, class... _Args> 366_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 367format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, 368 const _Args&... __args) { 369 // TODO FMT Improve PoC: using std::string is inefficient. 370 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)); 371 iter_difference_t<_OutIt> __s = __str.size(); 372 iter_difference_t<_OutIt> __m = 373 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 374 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 375 return {_VSTD::move(__out_it), __s}; 376} 377 378#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 379template <output_iterator<const wchar_t&> _OutIt, class... _Args> 380_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 381format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, 382 const _Args&... __args) { 383 // TODO FMT Improve PoC: using std::string is inefficient. 384 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)); 385 iter_difference_t<_OutIt> __s = __str.size(); 386 iter_difference_t<_OutIt> __m = 387 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 388 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 389 return {_VSTD::move(__out_it), __s}; 390} 391#endif 392 393template <class... _Args> 394_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 395formatted_size(string_view __fmt, const _Args&... __args) { 396 // TODO FMT Improve PoC: using std::string is inefficient. 397 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size(); 398} 399 400#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 401template <class... _Args> 402_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 403formatted_size(wstring_view __fmt, const _Args&... __args) { 404 // TODO FMT Improve PoC: using std::string is inefficient. 405 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size(); 406} 407#endif 408 409#ifndef _LIBCPP_HAS_NO_LOCALIZATION 410 411template <class _OutIt, class _CharT, class _FormatOutIt> 412requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 413 __vformat_to( 414 _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 415 basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 416 if constexpr (same_as<_OutIt, _FormatOutIt>) 417 return _VSTD::__format::__vformat_to( 418 basic_format_parse_context{__fmt, __args.__size()}, 419 _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 420 _VSTD::move(__loc))); 421 else { 422 __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 423 _VSTD::__format::__vformat_to( 424 basic_format_parse_context{__fmt, __args.__size()}, 425 _VSTD::__format_context_create(__buffer.make_output_iterator(), 426 __args, _VSTD::move(__loc))); 427 return _VSTD::move(__buffer).out(); 428 } 429} 430 431template <output_iterator<const char&> _OutIt> 432_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 433 _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 434 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 435 __args); 436} 437 438#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 439template <output_iterator<const wchar_t&> _OutIt> 440_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 441 _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 442 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 443 __args); 444} 445#endif 446 447template <output_iterator<const char&> _OutIt, class... _Args> 448_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 449 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) { 450 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 451 _VSTD::make_format_args(__args...)); 452} 453 454#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 455template <output_iterator<const wchar_t&> _OutIt, class... _Args> 456_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to( 457 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) { 458 return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 459 _VSTD::make_wformat_args(__args...)); 460} 461#endif 462 463_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 464vformat(locale __loc, string_view __fmt, format_args __args) { 465 string __res; 466 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 467 __args); 468 return __res; 469} 470 471#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 472_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 473vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 474 wstring __res; 475 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 476 __args); 477 return __res; 478} 479#endif 480 481template <class... _Args> 482_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 483format(locale __loc, string_view __fmt, const _Args&... __args) { 484 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 485 _VSTD::make_format_args(__args...)); 486} 487 488#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 489template <class... _Args> 490_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 491format(locale __loc, wstring_view __fmt, const _Args&... __args) { 492 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 493 _VSTD::make_wformat_args(__args...)); 494} 495#endif 496 497template <output_iterator<const char&> _OutIt, class... _Args> 498_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 499format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 500 string_view __fmt, const _Args&... __args) { 501 // TODO FMT Improve PoC: using std::string is inefficient. 502 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 503 _VSTD::make_format_args(__args...)); 504 iter_difference_t<_OutIt> __s = __str.size(); 505 iter_difference_t<_OutIt> __m = 506 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s); 507 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it)); 508 return {_VSTD::move(__out_it), __s}; 509} 510 511#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 512template <output_iterator<const wchar_t&> _OutIt, class... _Args> 513_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 514format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, 515 wstring_view __fmt, const _Args&... __args) { 516 // TODO FMT Improve PoC: using std::string is inefficient. 517 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt, 518 _VSTD::make_wformat_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#endif 526 527template <class... _Args> 528_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 529formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { 530 // TODO FMT Improve PoC: using std::string is inefficient. 531 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 532 _VSTD::make_format_args(__args...)) 533 .size(); 534} 535 536#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 537template <class... _Args> 538_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 539formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { 540 // TODO FMT Improve PoC: using std::string is inefficient. 541 return _VSTD::vformat(_VSTD::move(__loc), __fmt, 542 _VSTD::make_wformat_args(__args...)) 543 .size(); 544} 545#endif 546 547#endif // _LIBCPP_HAS_NO_LOCALIZATION 548 549#endif //_LIBCPP_STD_VER > 17 550 551_LIBCPP_END_NAMESPACE_STD 552 553#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 554 555#endif // _LIBCPP_FORMAT 556