1bdd1243dSDimitry Andric // -*- C++ -*- 2bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 3bdd1243dSDimitry Andric // 4bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7bdd1243dSDimitry Andric // 8bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 10bdd1243dSDimitry Andric #ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS 11bdd1243dSDimitry Andric #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #include <__algorithm/clamp.h> 14bdd1243dSDimitry Andric #include <__concepts/convertible_to.h> 15bdd1243dSDimitry Andric #include <__concepts/same_as.h> 16bdd1243dSDimitry Andric #include <__config> 17bdd1243dSDimitry Andric #include <__format/buffer.h> 18bdd1243dSDimitry Andric #include <__format/format_arg.h> 19bdd1243dSDimitry Andric #include <__format/format_arg_store.h> 20bdd1243dSDimitry Andric #include <__format/format_args.h> 21bdd1243dSDimitry Andric #include <__format/format_context.h> 22bdd1243dSDimitry Andric #include <__format/format_error.h> 23bdd1243dSDimitry Andric #include <__format/format_parse_context.h> 24bdd1243dSDimitry Andric #include <__format/format_string.h> 25bdd1243dSDimitry Andric #include <__format/format_to_n_result.h> 26bdd1243dSDimitry Andric #include <__format/formatter.h> 27bdd1243dSDimitry Andric #include <__format/formatter_bool.h> 28bdd1243dSDimitry Andric #include <__format/formatter_char.h> 29bdd1243dSDimitry Andric #include <__format/formatter_floating_point.h> 30bdd1243dSDimitry Andric #include <__format/formatter_integer.h> 31bdd1243dSDimitry Andric #include <__format/formatter_pointer.h> 32bdd1243dSDimitry Andric #include <__format/formatter_string.h> 33bdd1243dSDimitry Andric #include <__format/parser_std_format_spec.h> 34bdd1243dSDimitry Andric #include <__iterator/back_insert_iterator.h> 3506c3fb27SDimitry Andric #include <__iterator/concepts.h> 36bdd1243dSDimitry Andric #include <__iterator/incrementable_traits.h> 3706c3fb27SDimitry Andric #include <__iterator/iterator_traits.h> // iter_value_t 38bdd1243dSDimitry Andric #include <__variant/monostate.h> 39bdd1243dSDimitry Andric #include <array> 40bdd1243dSDimitry Andric #include <string> 41bdd1243dSDimitry Andric #include <string_view> 42bdd1243dSDimitry Andric 43bdd1243dSDimitry Andric #ifndef _LIBCPP_HAS_NO_LOCALIZATION 44*0fca6ea1SDimitry Andric # include <__locale> 45bdd1243dSDimitry Andric #endif 46bdd1243dSDimitry Andric 47bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 48bdd1243dSDimitry Andric # pragma GCC system_header 49bdd1243dSDimitry Andric #endif 50bdd1243dSDimitry Andric 51b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 52b3edf446SDimitry Andric #include <__undef_macros> 53b3edf446SDimitry Andric 54bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 55bdd1243dSDimitry Andric 5606c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 57bdd1243dSDimitry Andric 58bdd1243dSDimitry Andric // TODO FMT Evaluate which templates should be external templates. This 59bdd1243dSDimitry Andric // improves the efficiency of the header. However since the header is still 60bdd1243dSDimitry Andric // under heavy development and not all classes are stable it makes no sense 61bdd1243dSDimitry Andric // to do this optimization now. 62bdd1243dSDimitry Andric 63bdd1243dSDimitry Andric using format_args = basic_format_args<format_context>; 64bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 65bdd1243dSDimitry Andric using wformat_args = basic_format_args<wformat_context>; 66bdd1243dSDimitry Andric # endif 67bdd1243dSDimitry Andric 68bdd1243dSDimitry Andric template <class _Context = format_context, class... _Args> 69*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { 70*0fca6ea1SDimitry Andric return std::__format_arg_store<_Context, _Args...>(__args...); 71bdd1243dSDimitry Andric } 72bdd1243dSDimitry Andric 73bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 74bdd1243dSDimitry Andric template <class... _Args> 75*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&... __args) { 76*0fca6ea1SDimitry Andric return std::__format_arg_store<wformat_context, _Args...>(__args...); 77bdd1243dSDimitry Andric } 78bdd1243dSDimitry Andric # endif 79bdd1243dSDimitry Andric 80bdd1243dSDimitry Andric namespace __format { 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric /// Helper class parse and handle argument. 83bdd1243dSDimitry Andric /// 84bdd1243dSDimitry Andric /// When parsing a handle which is not enabled the code is ill-formed. 85bdd1243dSDimitry Andric /// This helper uses the parser of the appropriate formatter for the stored type. 86bdd1243dSDimitry Andric template <class _CharT> 87bdd1243dSDimitry Andric class _LIBCPP_TEMPLATE_VIS __compile_time_handle { 88bdd1243dSDimitry Andric public: 8906c3fb27SDimitry Andric template <class _ParseContext> 9006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const { 9106c3fb27SDimitry Andric __parse_(__ctx); 9206c3fb27SDimitry Andric } 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric template <class _Tp> 95bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 9606c3fb27SDimitry Andric __parse_ = [](basic_format_parse_context<_CharT>& __ctx) { 97bdd1243dSDimitry Andric formatter<_Tp, _CharT> __f; 9806c3fb27SDimitry Andric __ctx.advance_to(__f.parse(__ctx)); 99bdd1243dSDimitry Andric }; 100bdd1243dSDimitry Andric } 101bdd1243dSDimitry Andric 102bdd1243dSDimitry Andric // Before calling __parse the proper handler needs to be set with __enable. 103bdd1243dSDimitry Andric // The default handler isn't a core constant expression. 104bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 105bdd1243dSDimitry Andric : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {} 106bdd1243dSDimitry Andric 107bdd1243dSDimitry Andric private: 108bdd1243dSDimitry Andric void (*__parse_)(basic_format_parse_context<_CharT>&); 109bdd1243dSDimitry Andric }; 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric // Dummy format_context only providing the parts used during constant 112bdd1243dSDimitry Andric // validation of the basic_format_string. 113bdd1243dSDimitry Andric template <class _CharT> 114bdd1243dSDimitry Andric struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 115bdd1243dSDimitry Andric public: 116bdd1243dSDimitry Andric using char_type = _CharT; 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 119bdd1243dSDimitry Andric const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 120bdd1243dSDimitry Andric : __args_(__args), __handles_(__handles), __size_(__size) {} 121bdd1243dSDimitry Andric 122bdd1243dSDimitry Andric // During the compile-time validation nothing needs to be written. 123bdd1243dSDimitry Andric // Therefore all operations of this iterator are a NOP. 124bdd1243dSDimitry Andric struct iterator { 125bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 126bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 127bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 128bdd1243dSDimitry Andric }; 129bdd1243dSDimitry Andric 130bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 131bdd1243dSDimitry Andric if (__id >= __size_) 13206c3fb27SDimitry Andric std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 133bdd1243dSDimitry Andric return __args_[__id]; 134bdd1243dSDimitry Andric } 135bdd1243dSDimitry Andric 136bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 137bdd1243dSDimitry Andric if (__id >= __size_) 13806c3fb27SDimitry Andric std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 139bdd1243dSDimitry Andric return __handles_[__id]; 140bdd1243dSDimitry Andric } 141bdd1243dSDimitry Andric 142bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 143bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 144bdd1243dSDimitry Andric 145bdd1243dSDimitry Andric private: 146bdd1243dSDimitry Andric const __arg_t* __args_; 147bdd1243dSDimitry Andric const __compile_time_handle<_CharT>* __handles_; 148bdd1243dSDimitry Andric size_t __size_; 149bdd1243dSDimitry Andric }; 150bdd1243dSDimitry Andric 15106c3fb27SDimitry Andric // [format.string.std]/8 15206c3fb27SDimitry Andric // If { arg-idopt } is used in a width or precision, the value of the 15306c3fb27SDimitry Andric // corresponding formatting argument is used in its place. If the 15406c3fb27SDimitry Andric // corresponding formatting argument is not of standard signed or unsigned 15506c3fb27SDimitry Andric // integer type, or its value is negative for precision or non-positive for 15606c3fb27SDimitry Andric // width, an exception of type format_error is thrown. 15706c3fb27SDimitry Andric // 15806c3fb27SDimitry Andric // _HasPrecision does the formatter have a precision? 15906c3fb27SDimitry Andric template <class _CharT, class _Tp, bool _HasPrecision = false> 16006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument( 16106c3fb27SDimitry Andric basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) { 16206c3fb27SDimitry Andric auto __validate_type = [](__arg_t __type) { 16306c3fb27SDimitry Andric // LWG3720 originally allowed "signed or unsigned integer types", however 16406c3fb27SDimitry Andric // the final version explicitly changed it to "*standard* signed or unsigned 16506c3fb27SDimitry Andric // integer types". It's trivial to use 128-bit integrals in libc++'s 16606c3fb27SDimitry Andric // implementation, but other implementations may not implement it. 16706c3fb27SDimitry Andric // (Using a width or precision, that does not fit in 64-bits, sounds very 16806c3fb27SDimitry Andric // unlikely in real world code.) 169bdd1243dSDimitry Andric switch (__type) { 170bdd1243dSDimitry Andric case __arg_t::__int: 171bdd1243dSDimitry Andric case __arg_t::__long_long: 172bdd1243dSDimitry Andric case __arg_t::__unsigned: 173bdd1243dSDimitry Andric case __arg_t::__unsigned_long_long: 174bdd1243dSDimitry Andric return; 175bdd1243dSDimitry Andric 176bdd1243dSDimitry Andric default: 17706c3fb27SDimitry Andric std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type"); 178bdd1243dSDimitry Andric } 17906c3fb27SDimitry Andric }; 180bdd1243dSDimitry Andric 181bdd1243dSDimitry Andric formatter<_Tp, _CharT> __formatter; 182bdd1243dSDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 183bdd1243dSDimitry Andric if (__formatter.__parser_.__width_as_arg_) 18406c3fb27SDimitry Andric __validate_type(__ctx.arg(__formatter.__parser_.__width_)); 185bdd1243dSDimitry Andric 186bdd1243dSDimitry Andric if constexpr (_HasPrecision) 187bdd1243dSDimitry Andric if (__formatter.__parser_.__precision_as_arg_) 18806c3fb27SDimitry Andric __validate_type(__ctx.arg(__formatter.__parser_.__precision_)); 189bdd1243dSDimitry Andric } 190bdd1243dSDimitry Andric 191bdd1243dSDimitry Andric // This function is not user facing, so it can directly use the non-standard types of the "variant". 192bdd1243dSDimitry Andric template <class _CharT> 193cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg( 194cb14a3feSDimitry Andric basic_format_parse_context<_CharT>& __parse_ctx, 195bdd1243dSDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx, 196bdd1243dSDimitry Andric __arg_t __type) { 197bdd1243dSDimitry Andric switch (__type) { 198bdd1243dSDimitry Andric case __arg_t::__none: 199bdd1243dSDimitry Andric std::__throw_format_error("Invalid argument"); 200bdd1243dSDimitry Andric case __arg_t::__boolean: 201bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 202bdd1243dSDimitry Andric case __arg_t::__char_type: 203bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 204bdd1243dSDimitry Andric case __arg_t::__int: 205bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 206bdd1243dSDimitry Andric case __arg_t::__long_long: 207bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 208bdd1243dSDimitry Andric case __arg_t::__i128: 209bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 210bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 211bdd1243dSDimitry Andric # else 212bdd1243dSDimitry Andric std::__throw_format_error("Invalid argument"); 213bdd1243dSDimitry Andric # endif 214bdd1243dSDimitry Andric return; 215bdd1243dSDimitry Andric case __arg_t::__unsigned: 216bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 217bdd1243dSDimitry Andric case __arg_t::__unsigned_long_long: 218bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 219bdd1243dSDimitry Andric case __arg_t::__u128: 220bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 221bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 222bdd1243dSDimitry Andric # else 223bdd1243dSDimitry Andric std::__throw_format_error("Invalid argument"); 224bdd1243dSDimitry Andric # endif 225bdd1243dSDimitry Andric return; 226bdd1243dSDimitry Andric case __arg_t::__float: 227bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 228bdd1243dSDimitry Andric case __arg_t::__double: 229bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 230bdd1243dSDimitry Andric case __arg_t::__long_double: 231bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 232bdd1243dSDimitry Andric case __arg_t::__const_char_type_ptr: 233bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 234bdd1243dSDimitry Andric case __arg_t::__string_view: 235bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 236bdd1243dSDimitry Andric case __arg_t::__ptr: 237bdd1243dSDimitry Andric return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 238bdd1243dSDimitry Andric case __arg_t::__handle: 239bdd1243dSDimitry Andric std::__throw_format_error("Handle should use __compile_time_validate_handle_argument"); 240bdd1243dSDimitry Andric } 241bdd1243dSDimitry Andric std::__throw_format_error("Invalid argument"); 242bdd1243dSDimitry Andric } 243bdd1243dSDimitry Andric 24406c3fb27SDimitry Andric template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx> 24506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Iterator 246cb14a3feSDimitry Andric __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) { 24706c3fb27SDimitry Andric using _CharT = iter_value_t<_Iterator>; 248bdd1243dSDimitry Andric __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); 249bdd1243dSDimitry Andric 2508a4dda33SDimitry Andric if (__r.__last == __end) 2518a4dda33SDimitry Andric std::__throw_format_error("The argument index should end with a ':' or a '}'"); 2528a4dda33SDimitry Andric 25306c3fb27SDimitry Andric bool __parse = *__r.__last == _CharT(':'); 25406c3fb27SDimitry Andric switch (*__r.__last) { 255bdd1243dSDimitry Andric case _CharT(':'): 256bdd1243dSDimitry Andric // The arg-id has a format-specifier, advance the input to the format-spec. 25706c3fb27SDimitry Andric __parse_ctx.advance_to(__r.__last + 1); 258bdd1243dSDimitry Andric break; 259bdd1243dSDimitry Andric case _CharT('}'): 260bdd1243dSDimitry Andric // The arg-id has no format-specifier. 26106c3fb27SDimitry Andric __parse_ctx.advance_to(__r.__last); 262bdd1243dSDimitry Andric break; 263bdd1243dSDimitry Andric default: 26406c3fb27SDimitry Andric std::__throw_format_error("The argument index should end with a ':' or a '}'"); 265bdd1243dSDimitry Andric } 266bdd1243dSDimitry Andric 267bdd1243dSDimitry Andric if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 268bdd1243dSDimitry Andric __arg_t __type = __ctx.arg(__r.__value); 2691ac55f4cSDimitry Andric if (__type == __arg_t::__none) 27006c3fb27SDimitry Andric std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 2711ac55f4cSDimitry Andric else if (__type == __arg_t::__handle) 272bdd1243dSDimitry Andric __ctx.__handle(__r.__value).__parse(__parse_ctx); 2731ac55f4cSDimitry Andric else if (__parse) 274bdd1243dSDimitry Andric __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 275bdd1243dSDimitry Andric } else 2765f757f3fSDimitry Andric std::__visit_format_arg( 277bdd1243dSDimitry Andric [&](auto __arg) { 278bdd1243dSDimitry Andric if constexpr (same_as<decltype(__arg), monostate>) 27906c3fb27SDimitry Andric std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); 280bdd1243dSDimitry Andric else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 281bdd1243dSDimitry Andric __arg.format(__parse_ctx, __ctx); 282bdd1243dSDimitry Andric else { 283bdd1243dSDimitry Andric formatter<decltype(__arg), _CharT> __formatter; 284bdd1243dSDimitry Andric if (__parse) 285bdd1243dSDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 286bdd1243dSDimitry Andric __ctx.advance_to(__formatter.format(__arg, __ctx)); 287bdd1243dSDimitry Andric } 288bdd1243dSDimitry Andric }, 289bdd1243dSDimitry Andric __ctx.arg(__r.__value)); 290bdd1243dSDimitry Andric 291bdd1243dSDimitry Andric __begin = __parse_ctx.begin(); 292bdd1243dSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 293bdd1243dSDimitry Andric std::__throw_format_error("The replacement field misses a terminating '}'"); 294bdd1243dSDimitry Andric 295bdd1243dSDimitry Andric return ++__begin; 296bdd1243dSDimitry Andric } 297bdd1243dSDimitry Andric 298bdd1243dSDimitry Andric template <class _ParseCtx, class _Ctx> 299cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 300bdd1243dSDimitry Andric using _CharT = typename _ParseCtx::char_type; 301bdd1243dSDimitry Andric static_assert(same_as<typename _Ctx::char_type, _CharT>); 302bdd1243dSDimitry Andric 30306c3fb27SDimitry Andric auto __begin = __parse_ctx.begin(); 30406c3fb27SDimitry Andric auto __end = __parse_ctx.end(); 305bdd1243dSDimitry Andric typename _Ctx::iterator __out_it = __ctx.out(); 306bdd1243dSDimitry Andric while (__begin != __end) { 307bdd1243dSDimitry Andric switch (*__begin) { 308bdd1243dSDimitry Andric case _CharT('{'): 309bdd1243dSDimitry Andric ++__begin; 310bdd1243dSDimitry Andric if (__begin == __end) 311bdd1243dSDimitry Andric std::__throw_format_error("The format string terminates at a '{'"); 312bdd1243dSDimitry Andric 313bdd1243dSDimitry Andric if (*__begin != _CharT('{')) [[likely]] { 3145f757f3fSDimitry Andric __ctx.advance_to(std::move(__out_it)); 315cb14a3feSDimitry Andric __begin = __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 316bdd1243dSDimitry Andric __out_it = __ctx.out(); 317bdd1243dSDimitry Andric 318bdd1243dSDimitry Andric // The output is written and __begin points to the next character. So 319bdd1243dSDimitry Andric // start the next iteration. 320bdd1243dSDimitry Andric continue; 321bdd1243dSDimitry Andric } 322bdd1243dSDimitry Andric // The string is an escape character. 323bdd1243dSDimitry Andric break; 324bdd1243dSDimitry Andric 325bdd1243dSDimitry Andric case _CharT('}'): 326bdd1243dSDimitry Andric ++__begin; 327bdd1243dSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 328bdd1243dSDimitry Andric std::__throw_format_error("The format string contains an invalid escape sequence"); 329bdd1243dSDimitry Andric 330bdd1243dSDimitry Andric break; 331bdd1243dSDimitry Andric } 332bdd1243dSDimitry Andric 333bdd1243dSDimitry Andric // Copy the character to the output verbatim. 334bdd1243dSDimitry Andric *__out_it++ = *__begin++; 335bdd1243dSDimitry Andric } 336bdd1243dSDimitry Andric return __out_it; 337bdd1243dSDimitry Andric } 338bdd1243dSDimitry Andric 339bdd1243dSDimitry Andric } // namespace __format 340bdd1243dSDimitry Andric 3415f757f3fSDimitry Andric # if _LIBCPP_STD_VER >= 26 3425f757f3fSDimitry Andric template <class _CharT> 3435f757f3fSDimitry Andric struct _LIBCPP_TEMPLATE_VIS __runtime_format_string { 3445f757f3fSDimitry Andric private: 3455f757f3fSDimitry Andric basic_string_view<_CharT> __str_; 3465f757f3fSDimitry Andric 3475f757f3fSDimitry Andric template <class _Cp, class... _Args> 3485f757f3fSDimitry Andric friend struct _LIBCPP_TEMPLATE_VIS basic_format_string; 3495f757f3fSDimitry Andric 3505f757f3fSDimitry Andric public: 3515f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {} 3525f757f3fSDimitry Andric 3535f757f3fSDimitry Andric __runtime_format_string(const __runtime_format_string&) = delete; 3545f757f3fSDimitry Andric __runtime_format_string& operator=(const __runtime_format_string&) = delete; 3555f757f3fSDimitry Andric }; 3565f757f3fSDimitry Andric 3575f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; } 3585f757f3fSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3595f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept { 3605f757f3fSDimitry Andric return __fmt; 3615f757f3fSDimitry Andric } 3625f757f3fSDimitry Andric # endif 3635f757f3fSDimitry Andric # endif //_LIBCPP_STD_VER >= 26 3645f757f3fSDimitry Andric 365bdd1243dSDimitry Andric template <class _CharT, class... _Args> 366bdd1243dSDimitry Andric struct _LIBCPP_TEMPLATE_VIS basic_format_string { 367bdd1243dSDimitry Andric template <class _Tp> 368bdd1243dSDimitry Andric requires convertible_to<const _Tp&, basic_string_view<_CharT>> 369bdd1243dSDimitry Andric consteval basic_format_string(const _Tp& __str) : __str_{__str} { 370bdd1243dSDimitry Andric __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 371bdd1243dSDimitry Andric _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 372bdd1243dSDimitry Andric } 373bdd1243dSDimitry Andric 374cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; } 3755f757f3fSDimitry Andric # if _LIBCPP_STD_VER >= 26 3765f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_format_string(__runtime_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {} 3775f757f3fSDimitry Andric # endif 378bdd1243dSDimitry Andric 379bdd1243dSDimitry Andric private: 380bdd1243dSDimitry Andric basic_string_view<_CharT> __str_; 381bdd1243dSDimitry Andric 382bdd1243dSDimitry Andric using _Context = __format::__compile_time_basic_format_context<_CharT>; 383bdd1243dSDimitry Andric 384bdd1243dSDimitry Andric static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 385bdd1243dSDimitry Andric __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 386bdd1243dSDimitry Andric 387bdd1243dSDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 388bdd1243dSDimitry Andric using _Tp = remove_cvref_t<_Args>; 389bdd1243dSDimitry Andric __format::__compile_time_handle<_CharT> __handle; 390bdd1243dSDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 391bdd1243dSDimitry Andric __handle.template __enable<_Tp>(); 392bdd1243dSDimitry Andric 393bdd1243dSDimitry Andric return __handle; 394bdd1243dSDimitry Andric }()...}; 395bdd1243dSDimitry Andric }; 396bdd1243dSDimitry Andric 397bdd1243dSDimitry Andric template <class... _Args> 398bdd1243dSDimitry Andric using format_string = basic_format_string<char, type_identity_t<_Args>...>; 399bdd1243dSDimitry Andric 400bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 401bdd1243dSDimitry Andric template <class... _Args> 402bdd1243dSDimitry Andric using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; 403bdd1243dSDimitry Andric # endif 404bdd1243dSDimitry Andric 405bdd1243dSDimitry Andric template <class _OutIt, class _CharT, class _FormatOutIt> 406cb14a3feSDimitry Andric requires(output_iterator<_OutIt, const _CharT&>) 407cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it, 408cb14a3feSDimitry Andric basic_string_view<_CharT> __fmt, 409bdd1243dSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 410bdd1243dSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 411cb14a3feSDimitry Andric return std::__format::__vformat_to( 412cb14a3feSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args)); 413bdd1243dSDimitry Andric else { 4145f757f3fSDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)}; 4155f757f3fSDimitry Andric std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 4165f757f3fSDimitry Andric std::__format_context_create(__buffer.__make_output_iterator(), __args)); 4175f757f3fSDimitry Andric return std::move(__buffer).__out_it(); 418bdd1243dSDimitry Andric } 419bdd1243dSDimitry Andric } 420bdd1243dSDimitry Andric 421bdd1243dSDimitry Andric // The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 422bdd1243dSDimitry Andric // https://reviews.llvm.org/D110499#inline-1180704 423bdd1243dSDimitry Andric // TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 424bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt> 425cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 4265f757f3fSDimitry Andric return std::__vformat_to(std::move(__out_it), __fmt, __args); 427bdd1243dSDimitry Andric } 428bdd1243dSDimitry Andric 429bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 430bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt> 43106c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 432bdd1243dSDimitry Andric vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 4335f757f3fSDimitry Andric return std::__vformat_to(std::move(__out_it), __fmt, __args); 434bdd1243dSDimitry Andric } 435bdd1243dSDimitry Andric # endif 436bdd1243dSDimitry Andric 437bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args> 43806c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 439bdd1243dSDimitry Andric format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { 440cb14a3feSDimitry Andric return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_format_args(__args...)); 441bdd1243dSDimitry Andric } 442bdd1243dSDimitry Andric 443bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 444bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args> 44506c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 446bdd1243dSDimitry Andric format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { 447cb14a3feSDimitry Andric return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_wformat_args(__args...)); 448bdd1243dSDimitry Andric } 449bdd1243dSDimitry Andric # endif 450bdd1243dSDimitry Andric 45106c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 45206c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563. 45306c3fb27SDimitry Andric template <class = void> 454*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { 455bdd1243dSDimitry Andric string __res; 4565f757f3fSDimitry Andric std::vformat_to(std::back_inserter(__res), __fmt, __args); 457bdd1243dSDimitry Andric return __res; 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 46106c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 46206c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563. 46306c3fb27SDimitry Andric template <class = void> 464*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring 465bdd1243dSDimitry Andric vformat(wstring_view __fmt, wformat_args __args) { 466bdd1243dSDimitry Andric wstring __res; 4675f757f3fSDimitry Andric std::vformat_to(std::back_inserter(__res), __fmt, __args); 468bdd1243dSDimitry Andric return __res; 469bdd1243dSDimitry Andric } 470bdd1243dSDimitry Andric # endif 471bdd1243dSDimitry Andric 472bdd1243dSDimitry Andric template <class... _Args> 473*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string 47406c3fb27SDimitry Andric format(format_string<_Args...> __fmt, _Args&&... __args) { 4755f757f3fSDimitry Andric return std::vformat(__fmt.get(), std::make_format_args(__args...)); 476bdd1243dSDimitry Andric } 477bdd1243dSDimitry Andric 478bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 479bdd1243dSDimitry Andric template <class... _Args> 480*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring 481bdd1243dSDimitry Andric format(wformat_string<_Args...> __fmt, _Args&&... __args) { 4825f757f3fSDimitry Andric return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); 483bdd1243dSDimitry Andric } 484bdd1243dSDimitry Andric # endif 485bdd1243dSDimitry Andric 486bdd1243dSDimitry Andric template <class _Context, class _OutIt, class _CharT> 487cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 488cb14a3feSDimitry Andric __vformat_to_n(_OutIt __out_it, 489cb14a3feSDimitry Andric iter_difference_t<_OutIt> __n, 490bdd1243dSDimitry Andric basic_string_view<_CharT> __fmt, 491bdd1243dSDimitry Andric basic_format_args<_Context> __args) { 4925f757f3fSDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n}; 4935f757f3fSDimitry Andric std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 4945f757f3fSDimitry Andric std::__format_context_create(__buffer.__make_output_iterator(), __args)); 4955f757f3fSDimitry Andric return std::move(__buffer).__result(); 496bdd1243dSDimitry Andric } 497bdd1243dSDimitry Andric 498bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args> 49906c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 500bdd1243dSDimitry Andric format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { 5015f757f3fSDimitry Andric return std::__vformat_to_n<format_context>(std::move(__out_it), __n, __fmt.get(), std::make_format_args(__args...)); 502bdd1243dSDimitry Andric } 503bdd1243dSDimitry Andric 504bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 505bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args> 50606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> 507cb14a3feSDimitry Andric format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { 5085f757f3fSDimitry Andric return std::__vformat_to_n<wformat_context>(std::move(__out_it), __n, __fmt.get(), std::make_wformat_args(__args...)); 509bdd1243dSDimitry Andric } 510bdd1243dSDimitry Andric # endif 511bdd1243dSDimitry Andric 512bdd1243dSDimitry Andric template <class _CharT> 513bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 514bdd1243dSDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 5155f757f3fSDimitry Andric std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 5165f757f3fSDimitry Andric std::__format_context_create(__buffer.__make_output_iterator(), __args)); 5175f757f3fSDimitry Andric return std::move(__buffer).__result(); 518bdd1243dSDimitry Andric } 519bdd1243dSDimitry Andric 520bdd1243dSDimitry Andric template <class... _Args> 521*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 522bdd1243dSDimitry Andric formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { 5235f757f3fSDimitry Andric return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)}); 524bdd1243dSDimitry Andric } 525bdd1243dSDimitry Andric 526bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 527bdd1243dSDimitry Andric template <class... _Args> 528*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 529bdd1243dSDimitry Andric formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { 5305f757f3fSDimitry Andric return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); 531bdd1243dSDimitry Andric } 532bdd1243dSDimitry Andric # endif 533bdd1243dSDimitry Andric 534bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_LOCALIZATION 535bdd1243dSDimitry Andric 536bdd1243dSDimitry Andric template <class _OutIt, class _CharT, class _FormatOutIt> 537cb14a3feSDimitry Andric requires(output_iterator<_OutIt, const _CharT&>) 538cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to( 539cb14a3feSDimitry Andric _OutIt __out_it, 540cb14a3feSDimitry Andric locale __loc, 541cb14a3feSDimitry Andric basic_string_view<_CharT> __fmt, 542bdd1243dSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 543bdd1243dSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 544cb14a3feSDimitry Andric return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 5455f757f3fSDimitry Andric std::__format_context_create(std::move(__out_it), __args, std::move(__loc))); 546bdd1243dSDimitry Andric else { 5475f757f3fSDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)}; 5485f757f3fSDimitry Andric std::__format::__vformat_to( 549bdd1243dSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 5505f757f3fSDimitry Andric std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 5515f757f3fSDimitry Andric return std::move(__buffer).__out_it(); 552bdd1243dSDimitry Andric } 553bdd1243dSDimitry Andric } 554bdd1243dSDimitry Andric 555bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt> 556cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 557cb14a3feSDimitry Andric vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 558cb14a3feSDimitry Andric return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args); 559bdd1243dSDimitry Andric } 560bdd1243dSDimitry Andric 561bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 562bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt> 563cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 564cb14a3feSDimitry Andric vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 565cb14a3feSDimitry Andric return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args); 566bdd1243dSDimitry Andric } 567bdd1243dSDimitry Andric # endif 568bdd1243dSDimitry Andric 569bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args> 57006c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 571bdd1243dSDimitry Andric format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 572cb14a3feSDimitry Andric return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 573bdd1243dSDimitry Andric } 574bdd1243dSDimitry Andric 575bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 576bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args> 57706c3fb27SDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt 578bdd1243dSDimitry Andric format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 579cb14a3feSDimitry Andric return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 580bdd1243dSDimitry Andric } 581bdd1243dSDimitry Andric # endif 582bdd1243dSDimitry Andric 58306c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 58406c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563. 58506c3fb27SDimitry Andric template <class = void> 586*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string 587bdd1243dSDimitry Andric vformat(locale __loc, string_view __fmt, format_args __args) { 588bdd1243dSDimitry Andric string __res; 589cb14a3feSDimitry Andric std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); 590bdd1243dSDimitry Andric return __res; 591bdd1243dSDimitry Andric } 592bdd1243dSDimitry Andric 593bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 59406c3fb27SDimitry Andric // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup 59506c3fb27SDimitry Andric // fires too eagerly, see http://llvm.org/PR61563. 59606c3fb27SDimitry Andric template <class = void> 597*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring 598bdd1243dSDimitry Andric vformat(locale __loc, wstring_view __fmt, wformat_args __args) { 599bdd1243dSDimitry Andric wstring __res; 600cb14a3feSDimitry Andric std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); 601bdd1243dSDimitry Andric return __res; 602bdd1243dSDimitry Andric } 603bdd1243dSDimitry Andric # endif 604bdd1243dSDimitry Andric 605bdd1243dSDimitry Andric template <class... _Args> 606*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string 60706c3fb27SDimitry Andric format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 608cb14a3feSDimitry Andric return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 609bdd1243dSDimitry Andric } 610bdd1243dSDimitry Andric 611bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 612bdd1243dSDimitry Andric template <class... _Args> 613*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring 614bdd1243dSDimitry Andric format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 615cb14a3feSDimitry Andric return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 616bdd1243dSDimitry Andric } 617bdd1243dSDimitry Andric # endif 618bdd1243dSDimitry Andric 619bdd1243dSDimitry Andric template <class _Context, class _OutIt, class _CharT> 620cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n( 621cb14a3feSDimitry Andric _OutIt __out_it, 622cb14a3feSDimitry Andric iter_difference_t<_OutIt> __n, 623cb14a3feSDimitry Andric locale __loc, 624cb14a3feSDimitry Andric basic_string_view<_CharT> __fmt, 625bdd1243dSDimitry Andric basic_format_args<_Context> __args) { 6265f757f3fSDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n}; 6275f757f3fSDimitry Andric std::__format::__vformat_to( 628bdd1243dSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 6295f757f3fSDimitry Andric std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 6305f757f3fSDimitry Andric return std::move(__buffer).__result(); 631bdd1243dSDimitry Andric } 632bdd1243dSDimitry Andric 633bdd1243dSDimitry Andric template <output_iterator<const char&> _OutIt, class... _Args> 634cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n( 635cb14a3feSDimitry Andric _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 636cb14a3feSDimitry Andric return std::__vformat_to_n<format_context>( 637cb14a3feSDimitry Andric std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_format_args(__args...)); 638bdd1243dSDimitry Andric } 639bdd1243dSDimitry Andric 640bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 641bdd1243dSDimitry Andric template <output_iterator<const wchar_t&> _OutIt, class... _Args> 642cb14a3feSDimitry Andric _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n( 643cb14a3feSDimitry Andric _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 644cb14a3feSDimitry Andric return std::__vformat_to_n<wformat_context>( 645cb14a3feSDimitry Andric std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); 646bdd1243dSDimitry Andric } 647bdd1243dSDimitry Andric # endif 648bdd1243dSDimitry Andric 649bdd1243dSDimitry Andric template <class _CharT> 650bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 651bdd1243dSDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 6525f757f3fSDimitry Andric std::__format::__vformat_to( 653bdd1243dSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 6545f757f3fSDimitry Andric std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); 6555f757f3fSDimitry Andric return std::move(__buffer).__result(); 656bdd1243dSDimitry Andric } 657bdd1243dSDimitry Andric 658bdd1243dSDimitry Andric template <class... _Args> 659*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 660bdd1243dSDimitry Andric formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 6615f757f3fSDimitry Andric return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)}); 662bdd1243dSDimitry Andric } 663bdd1243dSDimitry Andric 664bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 665bdd1243dSDimitry Andric template <class... _Args> 666*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t 667bdd1243dSDimitry Andric formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 6685f757f3fSDimitry Andric return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); 669bdd1243dSDimitry Andric } 670bdd1243dSDimitry Andric # endif 671bdd1243dSDimitry Andric 672bdd1243dSDimitry Andric # endif // _LIBCPP_HAS_NO_LOCALIZATION 673bdd1243dSDimitry Andric 67406c3fb27SDimitry Andric #endif //_LIBCPP_STD_VER >= 20 675bdd1243dSDimitry Andric 676bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD 677bdd1243dSDimitry Andric 678b3edf446SDimitry Andric _LIBCPP_POP_MACROS 679b3edf446SDimitry Andric 680bdd1243dSDimitry Andric #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS 681