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