100798e50SMark de Wever // -*- C++ -*- 200798e50SMark de Wever //===----------------------------------------------------------------------===// 300798e50SMark de Wever // 400798e50SMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 500798e50SMark de Wever // See https://llvm.org/LICENSE.txt for license information. 600798e50SMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 700798e50SMark de Wever // 800798e50SMark de Wever //===----------------------------------------------------------------------===// 900798e50SMark de Wever 1000798e50SMark de Wever #ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS 1100798e50SMark de Wever #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS 1200798e50SMark de Wever 1300798e50SMark de Wever #include <__algorithm/clamp.h> 1400798e50SMark de Wever #include <__concepts/convertible_to.h> 1500798e50SMark de Wever #include <__concepts/same_as.h> 1600798e50SMark de Wever #include <__config> 1700798e50SMark de Wever #include <__format/buffer.h> 1800798e50SMark de Wever #include <__format/format_arg.h> 1900798e50SMark de Wever #include <__format/format_arg_store.h> 2000798e50SMark de Wever #include <__format/format_args.h> 2100798e50SMark de Wever #include <__format/format_context.h> 2200798e50SMark de Wever #include <__format/format_error.h> 2300798e50SMark de Wever #include <__format/format_parse_context.h> 2400798e50SMark de Wever #include <__format/format_string.h> 2500798e50SMark de Wever #include <__format/format_to_n_result.h> 2600798e50SMark de Wever #include <__format/formatter.h> 2700798e50SMark de Wever #include <__format/formatter_bool.h> 2800798e50SMark de Wever #include <__format/formatter_char.h> 2900798e50SMark de Wever #include <__format/formatter_floating_point.h> 3000798e50SMark de Wever #include <__format/formatter_integer.h> 3100798e50SMark de Wever #include <__format/formatter_pointer.h> 3200798e50SMark de Wever #include <__format/formatter_string.h> 3300798e50SMark de Wever #include <__format/parser_std_format_spec.h> 341562e514SLouis Dionne #include <__iterator/concepts.h> 3500798e50SMark de Wever #include <__iterator/incrementable_traits.h> 36d5ce68afSIan Anderson #include <__iterator/iterator_traits.h> // iter_value_t 3700798e50SMark de Wever #include <__variant/monostate.h> 3800798e50SMark de Wever #include <array> 3933fe4dc9SIan Anderson #include <string> 4000798e50SMark de Wever #include <string_view> 4100798e50SMark de Wever 42c6f3b7bcSNikolas Klauser #if _LIBCPP_HAS_LOCALIZATION 435bcb7814SNikolas Klauser # include <__locale> 4400798e50SMark de Wever #endif 4500798e50SMark de Wever 4600798e50SMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 4700798e50SMark de Wever # pragma GCC system_header 4800798e50SMark de Wever #endif 4900798e50SMark de Wever 507b462251SLouis Dionne _LIBCPP_PUSH_MACROS 517b462251SLouis Dionne #include <__undef_macros> 527b462251SLouis Dionne 5300798e50SMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD 5400798e50SMark de Wever 554f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 5600798e50SMark de Wever 5700798e50SMark de Wever // TODO FMT Evaluate which templates should be external templates. This 5800798e50SMark de Wever // improves the efficiency of the header. However since the header is still 5900798e50SMark de Wever // under heavy development and not all classes are stable it makes no sense 6000798e50SMark de Wever // to do this optimization now. 6100798e50SMark de Wever 6200798e50SMark de Wever using format_args = basic_format_args<format_context>; 63c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 6400798e50SMark de Wever using wformat_args = basic_format_args<wformat_context>; 6500798e50SMark de Wever # endif 6600798e50SMark de Wever 6700798e50SMark de Wever template <class _Context = format_context, class... _Args> 6883bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { 69683bc94eSLouis Dionne return std::__format_arg_store<_Context, _Args...>(__args...); 7000798e50SMark de Wever } 7100798e50SMark de Wever 72c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 7300798e50SMark de Wever template <class... _Args> 7483bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&... __args) { 75683bc94eSLouis Dionne return std::__format_arg_store<wformat_context, _Args...>(__args...); 7600798e50SMark de Wever } 7700798e50SMark de Wever # endif 7800798e50SMark de Wever 7900798e50SMark de Wever namespace __format { 8000798e50SMark de Wever 8100798e50SMark de Wever /// Helper class parse and handle argument. 8200798e50SMark de Wever /// 8300798e50SMark de Wever /// When parsing a handle which is not enabled the code is ill-formed. 8400798e50SMark de Wever /// This helper uses the parser of the appropriate formatter for the stored type. 8500798e50SMark de Wever template <class _CharT> 8600798e50SMark de Wever class _LIBCPP_TEMPLATE_VIS __compile_time_handle { 8700798e50SMark de Wever public: 88b51e8acdSMark de Wever template <class _ParseContext> 89b51e8acdSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const { 90b51e8acdSMark de Wever __parse_(__ctx); 91b51e8acdSMark de Wever } 9200798e50SMark de Wever 9300798e50SMark de Wever template <class _Tp> 9400798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 95b51e8acdSMark de Wever __parse_ = [](basic_format_parse_context<_CharT>& __ctx) { 9600798e50SMark de Wever formatter<_Tp, _CharT> __f; 97b51e8acdSMark de Wever __ctx.advance_to(__f.parse(__ctx)); 9800798e50SMark de Wever }; 9900798e50SMark de Wever } 10000798e50SMark de Wever 10100798e50SMark de Wever // Before calling __parse the proper handler needs to be set with __enable. 10200798e50SMark de Wever // The default handler isn't a core constant expression. 10300798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 104c1905b1cSMark de Wever : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {} 10500798e50SMark de Wever 10600798e50SMark de Wever private: 10700798e50SMark de Wever void (*__parse_)(basic_format_parse_context<_CharT>&); 10800798e50SMark de Wever }; 10900798e50SMark de Wever 11000798e50SMark de Wever // Dummy format_context only providing the parts used during constant 11100798e50SMark de Wever // validation of the basic_format_string. 11200798e50SMark de Wever template <class _CharT> 11300798e50SMark de Wever struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 11400798e50SMark de Wever public: 11500798e50SMark de Wever using char_type = _CharT; 11600798e50SMark de Wever 11700798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 11800798e50SMark de Wever const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 11900798e50SMark de Wever : __args_(__args), __handles_(__handles), __size_(__size) {} 12000798e50SMark de Wever 12100798e50SMark de Wever // During the compile-time validation nothing needs to be written. 12200798e50SMark de Wever // Therefore all operations of this iterator are a NOP. 12300798e50SMark de Wever struct iterator { 12400798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 12500798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 12600798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 12700798e50SMark de Wever }; 12800798e50SMark de Wever 12900798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 13000798e50SMark de Wever if (__id >= __size_) 131402eb2efSMark de Wever std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 13200798e50SMark de Wever return __args_[__id]; 13300798e50SMark de Wever } 13400798e50SMark de Wever 13500798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 13600798e50SMark de Wever if (__id >= __size_) 137402eb2efSMark de Wever std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 13800798e50SMark de Wever return __handles_[__id]; 13900798e50SMark de Wever } 14000798e50SMark de Wever 14100798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 14200798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 14300798e50SMark de Wever 14400798e50SMark de Wever private: 14500798e50SMark de Wever const __arg_t* __args_; 14600798e50SMark de Wever const __compile_time_handle<_CharT>* __handles_; 14700798e50SMark de Wever size_t __size_; 14800798e50SMark de Wever }; 14900798e50SMark de Wever 150d8516518SMark de Wever // [format.string.std]/8 151d8516518SMark de Wever // If { arg-idopt } is used in a width or precision, the value of the 152d8516518SMark de Wever // corresponding formatting argument is used in its place. If the 153d8516518SMark de Wever // corresponding formatting argument is not of standard signed or unsigned 154d8516518SMark de Wever // integer type, or its value is negative for precision or non-positive for 155d8516518SMark de Wever // width, an exception of type format_error is thrown. 156d8516518SMark de Wever // 157d8516518SMark de Wever // _HasPrecision does the formatter have a precision? 158d8516518SMark de Wever template <class _CharT, class _Tp, bool _HasPrecision = false> 159d8516518SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument( 160d8516518SMark de Wever basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) { 161d8516518SMark de Wever auto __validate_type = [](__arg_t __type) { 162d8516518SMark de Wever // LWG3720 originally allowed "signed or unsigned integer types", however 163d8516518SMark de Wever // the final version explicitly changed it to "*standard* signed or unsigned 164d8516518SMark de Wever // integer types". It's trivial to use 128-bit integrals in libc++'s 165d8516518SMark de Wever // implementation, but other implementations may not implement it. 166d8516518SMark de Wever // (Using a width or precision, that does not fit in 64-bits, sounds very 167d8516518SMark de Wever // unlikely in real world code.) 16800798e50SMark de Wever switch (__type) { 16900798e50SMark de Wever case __arg_t::__int: 17000798e50SMark de Wever case __arg_t::__long_long: 17100798e50SMark de Wever case __arg_t::__unsigned: 17200798e50SMark de Wever case __arg_t::__unsigned_long_long: 17300798e50SMark de Wever return; 17400798e50SMark de Wever 17500798e50SMark de Wever default: 176d8516518SMark de Wever std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type"); 17700798e50SMark de Wever } 178d8516518SMark de Wever }; 17900798e50SMark de Wever 18000798e50SMark de Wever formatter<_Tp, _CharT> __formatter; 18100798e50SMark de Wever __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 18200798e50SMark de Wever if (__formatter.__parser_.__width_as_arg_) 183d8516518SMark de Wever __validate_type(__ctx.arg(__formatter.__parser_.__width_)); 18400798e50SMark de Wever 18500798e50SMark de Wever if constexpr (_HasPrecision) 18600798e50SMark de Wever if (__formatter.__parser_.__precision_as_arg_) 187d8516518SMark de Wever __validate_type(__ctx.arg(__formatter.__parser_.__precision_)); 18800798e50SMark de Wever } 18900798e50SMark de Wever 190e948cab0SMark de Wever // This function is not user facing, so it can directly use the non-standard types of the "variant". 19100798e50SMark de Wever template <class _CharT> 1929783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg( 1939783f28cSLouis Dionne basic_format_parse_context<_CharT>& __parse_ctx, 19400798e50SMark de Wever __compile_time_basic_format_context<_CharT>& __ctx, 19500798e50SMark de Wever __arg_t __type) { 19600798e50SMark de Wever switch (__type) { 19700798e50SMark de Wever case __arg_t::__none: 198c1905b1cSMark de Wever std::__throw_format_error("Invalid argument"); 19900798e50SMark de Wever case __arg_t::__boolean: 20000798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 20100798e50SMark de Wever case __arg_t::__char_type: 20200798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 20300798e50SMark de Wever case __arg_t::__int: 20400798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 20500798e50SMark de Wever case __arg_t::__long_long: 20600798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 20700798e50SMark de Wever case __arg_t::__i128: 208ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 20900798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 21000798e50SMark de Wever # else 211c1905b1cSMark de Wever std::__throw_format_error("Invalid argument"); 21200798e50SMark de Wever # endif 21300798e50SMark de Wever return; 21400798e50SMark de Wever case __arg_t::__unsigned: 21500798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 21600798e50SMark de Wever case __arg_t::__unsigned_long_long: 21700798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 21800798e50SMark de Wever case __arg_t::__u128: 219ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 22000798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 22100798e50SMark de Wever # else 222c1905b1cSMark de Wever std::__throw_format_error("Invalid argument"); 22300798e50SMark de Wever # endif 22400798e50SMark de Wever return; 22500798e50SMark de Wever case __arg_t::__float: 22600798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 22700798e50SMark de Wever case __arg_t::__double: 22800798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 22900798e50SMark de Wever case __arg_t::__long_double: 23000798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 23100798e50SMark de Wever case __arg_t::__const_char_type_ptr: 23200798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 23300798e50SMark de Wever case __arg_t::__string_view: 23400798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 23500798e50SMark de Wever case __arg_t::__ptr: 23600798e50SMark de Wever return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 23700798e50SMark de Wever case __arg_t::__handle: 238c1905b1cSMark de Wever std::__throw_format_error("Handle should use __compile_time_validate_handle_argument"); 23900798e50SMark de Wever } 240c1905b1cSMark de Wever std::__throw_format_error("Invalid argument"); 24100798e50SMark de Wever } 24200798e50SMark de Wever 2431562e514SLouis Dionne template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx> 2441562e514SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr _Iterator 2459783f28cSLouis Dionne __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) { 2461562e514SLouis Dionne using _CharT = iter_value_t<_Iterator>; 247261b5abfSMark de Wever __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); 24800798e50SMark de Wever 2498930d04dSMark de Wever if (__r.__last == __end) 2508930d04dSMark de Wever std::__throw_format_error("The argument index should end with a ':' or a '}'"); 2518930d04dSMark de Wever 2521562e514SLouis Dionne bool __parse = *__r.__last == _CharT(':'); 2531562e514SLouis Dionne switch (*__r.__last) { 25400798e50SMark de Wever case _CharT(':'): 25500798e50SMark de Wever // The arg-id has a format-specifier, advance the input to the format-spec. 2561562e514SLouis Dionne __parse_ctx.advance_to(__r.__last + 1); 25700798e50SMark de Wever break; 25800798e50SMark de Wever case _CharT('}'): 25900798e50SMark de Wever // The arg-id has no format-specifier. 2601562e514SLouis Dionne __parse_ctx.advance_to(__r.__last); 26100798e50SMark de Wever break; 26200798e50SMark de Wever default: 263402eb2efSMark de Wever std::__throw_format_error("The argument index should end with a ':' or a '}'"); 26400798e50SMark de Wever } 26500798e50SMark de Wever 26600798e50SMark de Wever if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 26700798e50SMark de Wever __arg_t __type = __ctx.arg(__r.__value); 268ac44dadcSMark de Wever if (__type == __arg_t::__none) 269402eb2efSMark de Wever std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 270ac44dadcSMark de Wever else if (__type == __arg_t::__handle) 27100798e50SMark de Wever __ctx.__handle(__r.__value).__parse(__parse_ctx); 272ac44dadcSMark de Wever else if (__parse) 27300798e50SMark de Wever __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 27400798e50SMark de Wever } else 27577a00c0dSLouis Dionne std::__visit_format_arg( 27600798e50SMark de Wever [&](auto __arg) { 27700798e50SMark de Wever if constexpr (same_as<decltype(__arg), monostate>) 278402eb2efSMark de Wever std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 27900798e50SMark de Wever else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 28000798e50SMark de Wever __arg.format(__parse_ctx, __ctx); 28100798e50SMark de Wever else { 28200798e50SMark de Wever formatter<decltype(__arg), _CharT> __formatter; 28300798e50SMark de Wever if (__parse) 28400798e50SMark de Wever __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 28500798e50SMark de Wever __ctx.advance_to(__formatter.format(__arg, __ctx)); 28600798e50SMark de Wever } 28700798e50SMark de Wever }, 28800798e50SMark de Wever __ctx.arg(__r.__value)); 28900798e50SMark de Wever 29000798e50SMark de Wever __begin = __parse_ctx.begin(); 29100798e50SMark de Wever if (__begin == __end || *__begin != _CharT('}')) 292c1905b1cSMark de Wever std::__throw_format_error("The replacement field misses a terminating '}'"); 29300798e50SMark de Wever 29400798e50SMark de Wever return ++__begin; 29500798e50SMark de Wever } 29600798e50SMark de Wever 29700798e50SMark de Wever template <class _ParseCtx, class _Ctx> 2989783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 29900798e50SMark de Wever using _CharT = typename _ParseCtx::char_type; 30000798e50SMark de Wever static_assert(same_as<typename _Ctx::char_type, _CharT>); 30100798e50SMark de Wever 3021562e514SLouis Dionne auto __begin = __parse_ctx.begin(); 3031562e514SLouis Dionne auto __end = __parse_ctx.end(); 30400798e50SMark de Wever typename _Ctx::iterator __out_it = __ctx.out(); 30500798e50SMark de Wever while (__begin != __end) { 30600798e50SMark de Wever switch (*__begin) { 30700798e50SMark de Wever case _CharT('{'): 30800798e50SMark de Wever ++__begin; 30900798e50SMark de Wever if (__begin == __end) 310c1905b1cSMark de Wever std::__throw_format_error("The format string terminates at a '{'"); 31100798e50SMark de Wever 31200798e50SMark de Wever if (*__begin != _CharT('{')) [[likely]] { 31377a00c0dSLouis Dionne __ctx.advance_to(std::move(__out_it)); 3149783f28cSLouis Dionne __begin = __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 31500798e50SMark de Wever __out_it = __ctx.out(); 31600798e50SMark de Wever 31700798e50SMark de Wever // The output is written and __begin points to the next character. So 31800798e50SMark de Wever // start the next iteration. 31900798e50SMark de Wever continue; 32000798e50SMark de Wever } 32100798e50SMark de Wever // The string is an escape character. 32200798e50SMark de Wever break; 32300798e50SMark de Wever 32400798e50SMark de Wever case _CharT('}'): 32500798e50SMark de Wever ++__begin; 32600798e50SMark de Wever if (__begin == __end || *__begin != _CharT('}')) 327c1905b1cSMark de Wever std::__throw_format_error("The format string contains an invalid escape sequence"); 32800798e50SMark de Wever 32900798e50SMark de Wever break; 33000798e50SMark de Wever } 33100798e50SMark de Wever 33200798e50SMark de Wever // Copy the character to the output verbatim. 33300798e50SMark de Wever *__out_it++ = *__begin++; 33400798e50SMark de Wever } 33500798e50SMark de Wever return __out_it; 33600798e50SMark de Wever } 33700798e50SMark de Wever 33800798e50SMark de Wever } // namespace __format 33900798e50SMark de Wever 34092d9f232SMark de Wever # if _LIBCPP_STD_VER >= 26 34192d9f232SMark de Wever template <class _CharT> 34292d9f232SMark de Wever struct _LIBCPP_TEMPLATE_VIS __runtime_format_string { 34392d9f232SMark de Wever private: 34492d9f232SMark de Wever basic_string_view<_CharT> __str_; 34592d9f232SMark de Wever 34692d9f232SMark de Wever template <class _Cp, class... _Args> 34792d9f232SMark de Wever friend struct _LIBCPP_TEMPLATE_VIS basic_format_string; 34892d9f232SMark de Wever 34992d9f232SMark de Wever public: 35092d9f232SMark de Wever _LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {} 35192d9f232SMark de Wever 35292d9f232SMark de Wever __runtime_format_string(const __runtime_format_string&) = delete; 35392d9f232SMark de Wever __runtime_format_string& operator=(const __runtime_format_string&) = delete; 35492d9f232SMark de Wever }; 35592d9f232SMark de Wever 35692d9f232SMark de Wever _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; } 357c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 35892d9f232SMark de Wever _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept { 35992d9f232SMark de Wever return __fmt; 36092d9f232SMark de Wever } 36192d9f232SMark de Wever # endif 36292d9f232SMark de Wever # endif // _LIBCPP_STD_VER >= 26 36392d9f232SMark de Wever 36400798e50SMark de Wever template <class _CharT, class... _Args> 36500798e50SMark de Wever struct _LIBCPP_TEMPLATE_VIS basic_format_string { 36600798e50SMark de Wever template <class _Tp> 36700798e50SMark de Wever requires convertible_to<const _Tp&, basic_string_view<_CharT>> 36800798e50SMark de Wever consteval basic_format_string(const _Tp& __str) : __str_{__str} { 36900798e50SMark de Wever __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 37000798e50SMark de Wever _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 37100798e50SMark de Wever } 37200798e50SMark de Wever 3739783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; } 37492d9f232SMark de Wever # if _LIBCPP_STD_VER >= 26 37592d9f232SMark de Wever _LIBCPP_HIDE_FROM_ABI basic_format_string(__runtime_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {} 37692d9f232SMark de Wever # endif 37700798e50SMark de Wever 37800798e50SMark de Wever private: 37900798e50SMark de Wever basic_string_view<_CharT> __str_; 38000798e50SMark de Wever 381f6958523SNikolas Klauser using _Context _LIBCPP_NODEBUG = __format::__compile_time_basic_format_context<_CharT>; 38200798e50SMark de Wever 38300798e50SMark de Wever static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 38400798e50SMark de Wever __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 38500798e50SMark de Wever 38600798e50SMark de Wever static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 38700798e50SMark de Wever using _Tp = remove_cvref_t<_Args>; 38800798e50SMark de Wever __format::__compile_time_handle<_CharT> __handle; 38900798e50SMark de Wever if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 39000798e50SMark de Wever __handle.template __enable<_Tp>(); 39100798e50SMark de Wever 39200798e50SMark de Wever return __handle; 39300798e50SMark de Wever }()...}; 39400798e50SMark de Wever }; 39500798e50SMark de Wever 39600798e50SMark de Wever template <class... _Args> 39700798e50SMark de Wever using format_string = basic_format_string<char, type_identity_t<_Args>...>; 39800798e50SMark de Wever 399c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 40000798e50SMark de Wever template <class... _Args> 40100798e50SMark de Wever using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; 40200798e50SMark de Wever # endif 40300798e50SMark de Wever 40400798e50SMark de Wever template <class _OutIt, class _CharT, class _FormatOutIt> 4059783f28cSLouis Dionne requires(output_iterator<_OutIt, const _CharT&>) 4069783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it, 4079783f28cSLouis Dionne basic_string_view<_CharT> __fmt, 40800798e50SMark de Wever basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 40900798e50SMark de Wever if constexpr (same_as<_OutIt, _FormatOutIt>) 4109783f28cSLouis Dionne return std::__format::__vformat_to( 4119783f28cSLouis Dionne basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args)); 41200798e50SMark de Wever else { 413*14b44179SMark de Wever typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)}; 41477a00c0dSLouis Dionne std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 41577a00c0dSLouis Dionne std::__format_context_create(__buffer.__make_output_iterator(), __args)); 41677a00c0dSLouis Dionne return std::move(__buffer).__out_it(); 41700798e50SMark de Wever } 41800798e50SMark de Wever } 41900798e50SMark de Wever 42000798e50SMark de Wever // The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 42100798e50SMark de Wever // https://reviews.llvm.org/D110499#inline-1180704 42200798e50SMark de Wever // TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 42300798e50SMark de Wever template <output_iterator<const char&> _OutIt> 4249783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 42577a00c0dSLouis Dionne return std::__vformat_to(std::move(__out_it), __fmt, __args); 42600798e50SMark de Wever } 42700798e50SMark de Wever 428c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 42900798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt> 4303d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 43100798e50SMark de Wever vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 43277a00c0dSLouis Dionne return std::__vformat_to(std::move(__out_it), __fmt, __args); 43300798e50SMark de Wever } 43400798e50SMark de Wever # endif 43500798e50SMark de Wever 43600798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args> 4373d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 43800798e50SMark de Wever format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { 4399783f28cSLouis Dionne return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_format_args(__args...)); 44000798e50SMark de Wever } 44100798e50SMark de Wever 442c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 44300798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args> 4443d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 44500798e50SMark de Wever format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { 4469783f28cSLouis Dionne return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_wformat_args(__args...)); 44700798e50SMark de Wever } 44800798e50SMark de Wever # endif 44900798e50SMark de Wever 4503d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 4513d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563. 4523d334df5SLouis Dionne template <class = void> 45383bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { 454*14b44179SMark de Wever __format::__allocating_buffer<char> __buffer; 455*14b44179SMark de Wever std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args); 456*14b44179SMark de Wever return string{__buffer.__view()}; 45700798e50SMark de Wever } 45800798e50SMark de Wever 459c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 4603d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 4613d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563. 4623d334df5SLouis Dionne template <class = void> 46383bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring 46400798e50SMark de Wever vformat(wstring_view __fmt, wformat_args __args) { 465*14b44179SMark de Wever __format::__allocating_buffer<wchar_t> __buffer; 466*14b44179SMark de Wever std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args); 467*14b44179SMark de Wever return wstring{__buffer.__view()}; 46800798e50SMark de Wever } 46900798e50SMark de Wever # endif 47000798e50SMark de Wever 47100798e50SMark de Wever template <class... _Args> 47283bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string 4739c053e69SMark de Wever format(format_string<_Args...> __fmt, _Args&&... __args) { 47477a00c0dSLouis Dionne return std::vformat(__fmt.get(), std::make_format_args(__args...)); 47500798e50SMark de Wever } 47600798e50SMark de Wever 477c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 47800798e50SMark de Wever template <class... _Args> 47983bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring 48000798e50SMark de Wever format(wformat_string<_Args...> __fmt, _Args&&... __args) { 48177a00c0dSLouis Dionne return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); 48200798e50SMark de Wever } 48300798e50SMark de Wever # endif 48400798e50SMark de Wever 48500798e50SMark de Wever template <class _Context, class _OutIt, class _CharT> 4869783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 4879783f28cSLouis Dionne __vformat_to_n(_OutIt __out_it, 4889783f28cSLouis Dionne iter_difference_t<_OutIt> __n, 48900798e50SMark de Wever basic_string_view<_CharT> __fmt, 49000798e50SMark de Wever basic_format_args<_Context> __args) { 49177a00c0dSLouis Dionne __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n}; 49277a00c0dSLouis Dionne std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 49377a00c0dSLouis Dionne std::__format_context_create(__buffer.__make_output_iterator(), __args)); 49477a00c0dSLouis Dionne return std::move(__buffer).__result(); 49500798e50SMark de Wever } 49600798e50SMark de Wever 49700798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args> 4983d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 49900798e50SMark de Wever format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { 50077a00c0dSLouis Dionne return std::__vformat_to_n<format_context>(std::move(__out_it), __n, __fmt.get(), std::make_format_args(__args...)); 50100798e50SMark de Wever } 50200798e50SMark de Wever 503c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 50400798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args> 5053d334df5SLouis Dionne _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 5069783f28cSLouis Dionne format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { 50777a00c0dSLouis Dionne return std::__vformat_to_n<wformat_context>(std::move(__out_it), __n, __fmt.get(), std::make_wformat_args(__args...)); 50800798e50SMark de Wever } 50900798e50SMark de Wever # endif 51000798e50SMark de Wever 51100798e50SMark de Wever template <class _CharT> 51200798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 51300798e50SMark de Wever __format::__formatted_size_buffer<_CharT> __buffer; 51477a00c0dSLouis Dionne std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 51577a00c0dSLouis Dionne std::__format_context_create(__buffer.__make_output_iterator(), __args)); 51677a00c0dSLouis Dionne return std::move(__buffer).__result(); 51700798e50SMark de Wever } 51800798e50SMark de Wever 51900798e50SMark de Wever template <class... _Args> 52083bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 52100798e50SMark de Wever formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { 52277a00c0dSLouis Dionne return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)}); 52300798e50SMark de Wever } 52400798e50SMark de Wever 525c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 52600798e50SMark de Wever template <class... _Args> 52783bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 52800798e50SMark de Wever formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { 52977a00c0dSLouis Dionne return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); 53000798e50SMark de Wever } 53100798e50SMark de Wever # endif 53200798e50SMark de Wever 533c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_LOCALIZATION 53400798e50SMark de Wever 53500798e50SMark de Wever template <class _OutIt, class _CharT, class _FormatOutIt> 5369783f28cSLouis Dionne requires(output_iterator<_OutIt, const _CharT&>) 5379783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to( 5389783f28cSLouis Dionne _OutIt __out_it, 5399783f28cSLouis Dionne locale __loc, 5409783f28cSLouis Dionne basic_string_view<_CharT> __fmt, 54100798e50SMark de Wever basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 54200798e50SMark de Wever if constexpr (same_as<_OutIt, _FormatOutIt>) 5439783f28cSLouis Dionne return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 54477a00c0dSLouis Dionne std::__format_context_create(std::move(__out_it), __args, std::move(__loc))); 54500798e50SMark de Wever else { 546*14b44179SMark de Wever typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)}; 54777a00c0dSLouis Dionne std::__format::__vformat_to( 548261b5abfSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 54977a00c0dSLouis Dionne std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 55077a00c0dSLouis Dionne return std::move(__buffer).__out_it(); 55100798e50SMark de Wever } 55200798e50SMark de Wever } 55300798e50SMark de Wever 55400798e50SMark de Wever template <output_iterator<const char&> _OutIt> 5559783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 5569783f28cSLouis Dionne vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 5579783f28cSLouis Dionne return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args); 55800798e50SMark de Wever } 55900798e50SMark de Wever 560c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 56100798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt> 5629783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 5639783f28cSLouis Dionne vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 5649783f28cSLouis Dionne return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args); 56500798e50SMark de Wever } 56600798e50SMark de Wever # endif 56700798e50SMark de Wever 56800798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args> 5693d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 57000798e50SMark de Wever format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 5719783f28cSLouis Dionne return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 57200798e50SMark de Wever } 57300798e50SMark de Wever 574c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 57500798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args> 5763d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 57700798e50SMark de Wever format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 5789783f28cSLouis Dionne return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 57900798e50SMark de Wever } 58000798e50SMark de Wever # endif 58100798e50SMark de Wever 5823d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 5833d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563. 5843d334df5SLouis Dionne template <class = void> 58583bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string 58600798e50SMark de Wever vformat(locale __loc, string_view __fmt, format_args __args) { 587*14b44179SMark de Wever __format::__allocating_buffer<char> __buffer; 588*14b44179SMark de Wever std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args); 589*14b44179SMark de Wever return string{__buffer.__view()}; 59000798e50SMark de Wever } 59100798e50SMark de Wever 592c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 5933d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 5943d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563. 5953d334df5SLouis Dionne template <class = void> 59683bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring 59700798e50SMark de Wever vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 598*14b44179SMark de Wever __format::__allocating_buffer<wchar_t> __buffer; 599*14b44179SMark de Wever std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args); 600*14b44179SMark de Wever return wstring{__buffer.__view()}; 60100798e50SMark de Wever } 60200798e50SMark de Wever # endif 60300798e50SMark de Wever 60400798e50SMark de Wever template <class... _Args> 60583bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string 6069c053e69SMark de Wever format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 6079783f28cSLouis Dionne return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 60800798e50SMark de Wever } 60900798e50SMark de Wever 610c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 61100798e50SMark de Wever template <class... _Args> 61283bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring 61300798e50SMark de Wever format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 6149783f28cSLouis Dionne return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 61500798e50SMark de Wever } 61600798e50SMark de Wever # endif 61700798e50SMark de Wever 61800798e50SMark de Wever template <class _Context, class _OutIt, class _CharT> 6199783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n( 6209783f28cSLouis Dionne _OutIt __out_it, 6219783f28cSLouis Dionne iter_difference_t<_OutIt> __n, 6229783f28cSLouis Dionne locale __loc, 6239783f28cSLouis Dionne basic_string_view<_CharT> __fmt, 62400798e50SMark de Wever basic_format_args<_Context> __args) { 62577a00c0dSLouis Dionne __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n}; 62677a00c0dSLouis Dionne std::__format::__vformat_to( 627261b5abfSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 62877a00c0dSLouis Dionne std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 62977a00c0dSLouis Dionne return std::move(__buffer).__result(); 63000798e50SMark de Wever } 63100798e50SMark de Wever 63200798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args> 6339783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n( 6349783f28cSLouis Dionne _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 6359783f28cSLouis Dionne return std::__vformat_to_n<format_context>( 6369783f28cSLouis Dionne std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 63700798e50SMark de Wever } 63800798e50SMark de Wever 639c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 64000798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args> 6419783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n( 6429783f28cSLouis Dionne _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 6439783f28cSLouis Dionne return std::__vformat_to_n<wformat_context>( 6449783f28cSLouis Dionne std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 64500798e50SMark de Wever } 64600798e50SMark de Wever # endif 64700798e50SMark de Wever 64800798e50SMark de Wever template <class _CharT> 64900798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 65000798e50SMark de Wever __format::__formatted_size_buffer<_CharT> __buffer; 65177a00c0dSLouis Dionne std::__format::__vformat_to( 652261b5abfSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 65377a00c0dSLouis Dionne std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 65477a00c0dSLouis Dionne return std::move(__buffer).__result(); 65500798e50SMark de Wever } 65600798e50SMark de Wever 65700798e50SMark de Wever template <class... _Args> 65883bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 65900798e50SMark de Wever formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 66077a00c0dSLouis Dionne return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)}); 66100798e50SMark de Wever } 66200798e50SMark de Wever 663c6f3b7bcSNikolas Klauser # if _LIBCPP_HAS_WIDE_CHARACTERS 66400798e50SMark de Wever template <class... _Args> 66583bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 66600798e50SMark de Wever formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 66777a00c0dSLouis Dionne return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); 66800798e50SMark de Wever } 66900798e50SMark de Wever # endif 67000798e50SMark de Wever 671c6f3b7bcSNikolas Klauser # endif // _LIBCPP_HAS_LOCALIZATION 67200798e50SMark de Wever 6734f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20 67400798e50SMark de Wever 67500798e50SMark de Wever _LIBCPP_END_NAMESPACE_STD 67600798e50SMark de Wever 6777b462251SLouis Dionne _LIBCPP_POP_MACROS 6787b462251SLouis Dionne 67900798e50SMark de Wever #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS 680