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