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