1fe6060f1SDimitry Andric// -*- C++ -*- 2349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric// 4fe6060f1SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric// 8fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 9fe6060f1SDimitry Andric 10fe6060f1SDimitry Andric#ifndef _LIBCPP_FORMAT 11fe6060f1SDimitry Andric#define _LIBCPP_FORMAT 12fe6060f1SDimitry Andric 13fe6060f1SDimitry Andric/* 14fe6060f1SDimitry Andric 15fe6060f1SDimitry Andricnamespace std { 16349cc55cSDimitry Andric // [format.context], class template basic_format_context 1704eeddc0SDimitry Andric template<class Out, class charT> class basic_format_context; 18349cc55cSDimitry Andric using format_context = basic_format_context<unspecified, char>; 19349cc55cSDimitry Andric using wformat_context = basic_format_context<unspecified, wchar_t>; 20349cc55cSDimitry Andric 21349cc55cSDimitry Andric // [format.args], class template basic_format_args 2204eeddc0SDimitry Andric template<class Context> class basic_format_args; 23349cc55cSDimitry Andric using format_args = basic_format_args<format_context>; 24349cc55cSDimitry Andric using wformat_args = basic_format_args<wformat_context>; 25349cc55cSDimitry Andric 26*61cfbce3SDimitry Andric // [format.fmt.string], class template basic_format_string 2781ad6265SDimitry Andric template<class charT, class... Args> 28*61cfbce3SDimitry Andric struct basic_format_string { // since C++23, exposition only before C++23 29*61cfbce3SDimitry Andric private: 30*61cfbce3SDimitry Andric basic_string_view<charT> str; // exposition only 3181ad6265SDimitry Andric 32*61cfbce3SDimitry Andric public: 33*61cfbce3SDimitry Andric template<class T> consteval basic_format_string(const T& s); 34*61cfbce3SDimitry Andric 35*61cfbce3SDimitry Andric constexpr basic_string_view<charT> get() const noexcept { return str; } 36*61cfbce3SDimitry Andric }; 3781ad6265SDimitry Andric template<class... Args> 38*61cfbce3SDimitry Andric using format_string = // since C++23, exposition only before C++23 39*61cfbce3SDimitry Andric basic_format_string<char, type_identity_t<Args>...>; 4081ad6265SDimitry Andric template<class... Args> 41*61cfbce3SDimitry Andric using wformat_string = // since C++23, exposition only before C++23 42*61cfbce3SDimitry Andric basic_format_string<wchar_t, type_identity_t<Args>...>; 4381ad6265SDimitry Andric 44349cc55cSDimitry Andric // [format.functions], formatting functions 45349cc55cSDimitry Andric template<class... Args> 46753f127fSDimitry Andric string format(format-string<Args...> fmt, Args&&... args); 47349cc55cSDimitry Andric template<class... Args> 48753f127fSDimitry Andric wstring format(wformat-string<Args...> fmt, Args&&... args); 49349cc55cSDimitry Andric template<class... Args> 50753f127fSDimitry Andric string format(const locale& loc, format-string<Args...> fmt, Args&&... args); 51349cc55cSDimitry Andric template<class... Args> 52753f127fSDimitry Andric wstring format(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 53349cc55cSDimitry Andric 54349cc55cSDimitry Andric string vformat(string_view fmt, format_args args); 55349cc55cSDimitry Andric wstring vformat(wstring_view fmt, wformat_args args); 56349cc55cSDimitry Andric string vformat(const locale& loc, string_view fmt, format_args args); 57349cc55cSDimitry Andric wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); 58349cc55cSDimitry Andric 59349cc55cSDimitry Andric template<class Out, class... Args> 60753f127fSDimitry Andric Out format_to(Out out, format-string<Args...> fmt, Args&&... args); 61349cc55cSDimitry Andric template<class Out, class... Args> 62753f127fSDimitry Andric Out format_to(Out out, wformat-string<Args...> fmt, Args&&... args); 63349cc55cSDimitry Andric template<class Out, class... Args> 64753f127fSDimitry Andric Out format_to(Out out, const locale& loc, format-string<Args...> fmt, Args&&... args); 65349cc55cSDimitry Andric template<class Out, class... Args> 66753f127fSDimitry Andric Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, Args&&... args); 67349cc55cSDimitry Andric 68349cc55cSDimitry Andric template<class Out> 694824e7fdSDimitry Andric Out vformat_to(Out out, string_view fmt, format_args args); 70349cc55cSDimitry Andric template<class Out> 714824e7fdSDimitry Andric Out vformat_to(Out out, wstring_view fmt, wformat_args args); 72349cc55cSDimitry Andric template<class Out> 73349cc55cSDimitry Andric Out vformat_to(Out out, const locale& loc, string_view fmt, 744824e7fdSDimitry Andric format_args char> args); 75349cc55cSDimitry Andric template<class Out> 76349cc55cSDimitry Andric Out vformat_to(Out out, const locale& loc, wstring_view fmt, 774824e7fdSDimitry Andric wformat_args args); 78349cc55cSDimitry Andric 79349cc55cSDimitry Andric template<class Out> struct format_to_n_result { 80349cc55cSDimitry Andric Out out; 81349cc55cSDimitry Andric iter_difference_t<Out> size; 82349cc55cSDimitry Andric }; 83349cc55cSDimitry Andric template<class Out, class... Args> 84349cc55cSDimitry Andric format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 85753f127fSDimitry Andric format-string<Args...> fmt, Args&&... args); 86349cc55cSDimitry Andric template<class Out, class... Args> 87349cc55cSDimitry Andric format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 88753f127fSDimitry Andric wformat-string<Args...> fmt, Args&&... args); 89349cc55cSDimitry Andric template<class Out, class... Args> 90349cc55cSDimitry Andric format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 9181ad6265SDimitry Andric const locale& loc, format-string<Args...> fmt, 92753f127fSDimitry Andric Args&&... args); 93349cc55cSDimitry Andric template<class Out, class... Args> 94349cc55cSDimitry Andric format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 9581ad6265SDimitry Andric const locale& loc, wformat-string<Args...> fmt, 96753f127fSDimitry Andric Args&&... args); 97349cc55cSDimitry Andric 98349cc55cSDimitry Andric template<class... Args> 99753f127fSDimitry Andric size_t formatted_size(format-string<Args...> fmt, Args&&... args); 100349cc55cSDimitry Andric template<class... Args> 101753f127fSDimitry Andric size_t formatted_size(wformat-string<Args...> fmt, Args&&... args); 102349cc55cSDimitry Andric template<class... Args> 103753f127fSDimitry Andric size_t formatted_size(const locale& loc, format-string<Args...> fmt, Args&&... args); 104349cc55cSDimitry Andric template<class... Args> 105753f127fSDimitry Andric size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 106349cc55cSDimitry Andric 107349cc55cSDimitry Andric // [format.formatter], formatter 10804eeddc0SDimitry Andric template<class T, class charT = char> struct formatter; 109349cc55cSDimitry Andric 110349cc55cSDimitry Andric // [format.parse.ctx], class template basic_format_parse_context 11104eeddc0SDimitry Andric template<class charT> class basic_format_parse_context; 112349cc55cSDimitry Andric using format_parse_context = basic_format_parse_context<char>; 113349cc55cSDimitry Andric using wformat_parse_context = basic_format_parse_context<wchar_t>; 114349cc55cSDimitry Andric 115349cc55cSDimitry Andric // [format.arguments], arguments 116349cc55cSDimitry Andric // [format.arg], class template basic_format_arg 11704eeddc0SDimitry Andric template<class Context> class basic_format_arg; 118349cc55cSDimitry Andric 119349cc55cSDimitry Andric template<class Visitor, class Context> 120349cc55cSDimitry Andric see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); 121349cc55cSDimitry Andric 122349cc55cSDimitry Andric // [format.arg.store], class template format-arg-store 12304eeddc0SDimitry Andric template<class Context, class... Args> struct format-arg-store; // exposition only 124349cc55cSDimitry Andric 125349cc55cSDimitry Andric template<class Context = format_context, class... Args> 126349cc55cSDimitry Andric format-arg-store<Context, Args...> 127753f127fSDimitry Andric make_format_args(Args&&... args); 128349cc55cSDimitry Andric template<class... Args> 129349cc55cSDimitry Andric format-arg-store<wformat_context, Args...> 130753f127fSDimitry Andric make_wformat_args(Args&&... args); 131349cc55cSDimitry Andric 132fe6060f1SDimitry Andric // [format.error], class format_error 13304eeddc0SDimitry Andric class format_error; 134fe6060f1SDimitry Andric} 135fe6060f1SDimitry Andric 136fe6060f1SDimitry Andric*/ 137fe6060f1SDimitry Andric 13881ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler 139349cc55cSDimitry Andric// Make sure all feature-test macros are available. 1406e75b2fbSDimitry Andric#include <version> 141fcaf7f86SDimitry Andric// Enable the contents of the header only when libc++ was built with experimental features enabled. 1426e75b2fbSDimitry Andric#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 1436e75b2fbSDimitry Andric 14481ad6265SDimitry Andric#include <__algorithm/clamp.h> 145fe6060f1SDimitry Andric#include <__config> 146349cc55cSDimitry Andric#include <__debug> 14781ad6265SDimitry Andric#include <__format/buffer.h> 14881ad6265SDimitry Andric#include <__format/concepts.h> 14981ad6265SDimitry Andric#include <__format/enable_insertable.h> 150349cc55cSDimitry Andric#include <__format/format_arg.h> 15181ad6265SDimitry Andric#include <__format/format_arg_store.h> 152349cc55cSDimitry Andric#include <__format/format_args.h> 153349cc55cSDimitry Andric#include <__format/format_context.h> 154fe6060f1SDimitry Andric#include <__format/format_error.h> 155349cc55cSDimitry Andric#include <__format/format_fwd.h> 156fe6060f1SDimitry Andric#include <__format/format_parse_context.h> 157349cc55cSDimitry Andric#include <__format/format_string.h> 158349cc55cSDimitry Andric#include <__format/format_to_n_result.h> 159349cc55cSDimitry Andric#include <__format/formatter.h> 160349cc55cSDimitry Andric#include <__format/formatter_bool.h> 161349cc55cSDimitry Andric#include <__format/formatter_char.h> 16204eeddc0SDimitry Andric#include <__format/formatter_floating_point.h> 163349cc55cSDimitry Andric#include <__format/formatter_integer.h> 16404eeddc0SDimitry Andric#include <__format/formatter_pointer.h> 165349cc55cSDimitry Andric#include <__format/formatter_string.h> 166349cc55cSDimitry Andric#include <__format/parser_std_format_spec.h> 167fcaf7f86SDimitry Andric#include <__format/unicode.h> 16881ad6265SDimitry Andric#include <__iterator/back_insert_iterator.h> 16981ad6265SDimitry Andric#include <__iterator/incrementable_traits.h> 170349cc55cSDimitry Andric#include <__variant/monostate.h> 171349cc55cSDimitry Andric#include <array> 172349cc55cSDimitry Andric#include <concepts> 173349cc55cSDimitry Andric#include <string> 174349cc55cSDimitry Andric#include <string_view> 175349cc55cSDimitry Andric#include <type_traits> 176349cc55cSDimitry Andric 177349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION 178349cc55cSDimitry Andric#include <locale> 179349cc55cSDimitry Andric#endif 180fe6060f1SDimitry Andric 181fe6060f1SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 182fe6060f1SDimitry Andric# pragma GCC system_header 183fe6060f1SDimitry Andric#endif 184fe6060f1SDimitry Andric 185fe6060f1SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 186fe6060f1SDimitry Andric 187fe6060f1SDimitry Andric#if _LIBCPP_STD_VER > 17 188fe6060f1SDimitry Andric 189349cc55cSDimitry Andric// TODO FMT Move the implementation in this file to its own granular headers. 190349cc55cSDimitry Andric 191349cc55cSDimitry Andric// TODO FMT Evaluate which templates should be external templates. This 192349cc55cSDimitry Andric// improves the efficiency of the header. However since the header is still 193349cc55cSDimitry Andric// under heavy development and not all classes are stable it makes no sense 194349cc55cSDimitry Andric// to do this optimization now. 195349cc55cSDimitry Andric 196349cc55cSDimitry Andricusing format_args = basic_format_args<format_context>; 197349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 198349cc55cSDimitry Andricusing wformat_args = basic_format_args<wformat_context>; 199349cc55cSDimitry Andric#endif 200349cc55cSDimitry Andric 20181ad6265SDimitry Andrictemplate <class _Context = format_context, class... _Args> 202753f127fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { 203753f127fSDimitry Andric return _VSTD::__format_arg_store<_Context, _Args...>(__args...); 204349cc55cSDimitry Andric} 205349cc55cSDimitry Andric 206349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 207349cc55cSDimitry Andrictemplate <class... _Args> 208753f127fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) { 209753f127fSDimitry Andric return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...); 210349cc55cSDimitry Andric} 211349cc55cSDimitry Andric#endif 212349cc55cSDimitry Andric 213349cc55cSDimitry Andricnamespace __format { 214349cc55cSDimitry Andric 21581ad6265SDimitry Andric/// Helper class parse and handle argument. 21681ad6265SDimitry Andric/// 21781ad6265SDimitry Andric/// When parsing a handle which is not enabled the code is ill-formed. 21881ad6265SDimitry Andric/// This helper uses the parser of the appropriate formatter for the stored type. 21981ad6265SDimitry Andrictemplate <class _CharT> 22081ad6265SDimitry Andricclass _LIBCPP_TEMPLATE_VIS __compile_time_handle { 22181ad6265SDimitry Andricpublic: 22281ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI 22381ad6265SDimitry Andric constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } 22481ad6265SDimitry Andric 22581ad6265SDimitry Andric template <class _Tp> 22681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 22781ad6265SDimitry Andric __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { 22881ad6265SDimitry Andric formatter<_Tp, _CharT> __f; 22981ad6265SDimitry Andric __parse_ctx.advance_to(__f.parse(__parse_ctx)); 23081ad6265SDimitry Andric }; 23181ad6265SDimitry Andric } 23281ad6265SDimitry Andric 23381ad6265SDimitry Andric // Before calling __parse the proper handler needs to be set with __enable. 23481ad6265SDimitry Andric // The default handler isn't a core constant expression. 23581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 23681ad6265SDimitry Andric : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {} 23781ad6265SDimitry Andric 23881ad6265SDimitry Andricprivate: 23981ad6265SDimitry Andric void (*__parse_)(basic_format_parse_context<_CharT>&); 24081ad6265SDimitry Andric}; 24181ad6265SDimitry Andric 24281ad6265SDimitry Andric// Dummy format_context only providing the parts used during constant 243*61cfbce3SDimitry Andric// validation of the basic_format_string. 24481ad6265SDimitry Andrictemplate <class _CharT> 24581ad6265SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 24681ad6265SDimitry Andricpublic: 24781ad6265SDimitry Andric using char_type = _CharT; 24881ad6265SDimitry Andric 24981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 25081ad6265SDimitry Andric const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 25181ad6265SDimitry Andric : __args_(__args), __handles_(__handles), __size_(__size) {} 25281ad6265SDimitry Andric 25381ad6265SDimitry Andric // During the compile-time validation nothing needs to be written. 25481ad6265SDimitry Andric // Therefore all operations of this iterator are a NOP. 25581ad6265SDimitry Andric struct iterator { 25681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 25781ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 25881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 25981ad6265SDimitry Andric }; 26081ad6265SDimitry Andric 26181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 26281ad6265SDimitry Andric if (__id >= __size_) 26381ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 26481ad6265SDimitry Andric return __args_[__id]; 26581ad6265SDimitry Andric } 26681ad6265SDimitry Andric 26781ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 26881ad6265SDimitry Andric if (__id >= __size_) 26981ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 27081ad6265SDimitry Andric return __handles_[__id]; 27181ad6265SDimitry Andric } 27281ad6265SDimitry Andric 27381ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 27481ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 27581ad6265SDimitry Andric 27681ad6265SDimitry Andricprivate: 27781ad6265SDimitry Andric const __arg_t* __args_; 27881ad6265SDimitry Andric const __compile_time_handle<_CharT>* __handles_; 27981ad6265SDimitry Andric size_t __size_; 28081ad6265SDimitry Andric}; 28181ad6265SDimitry Andric 28281ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI 28381ad6265SDimitry Andricconstexpr void __compile_time_validate_integral(__arg_t __type) { 28481ad6265SDimitry Andric switch (__type) { 28581ad6265SDimitry Andric case __arg_t::__int: 28681ad6265SDimitry Andric case __arg_t::__long_long: 28781ad6265SDimitry Andric case __arg_t::__i128: 28881ad6265SDimitry Andric case __arg_t::__unsigned: 28981ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 29081ad6265SDimitry Andric case __arg_t::__u128: 29181ad6265SDimitry Andric return; 29281ad6265SDimitry Andric 29381ad6265SDimitry Andric default: 29481ad6265SDimitry Andric __throw_format_error("Argument isn't an integral type"); 29581ad6265SDimitry Andric } 29681ad6265SDimitry Andric} 29781ad6265SDimitry Andric 29881ad6265SDimitry Andric// _HasPrecision does the formatter have a precision? 29981ad6265SDimitry Andrictemplate <class _CharT, class _Tp, bool _HasPrecision = false> 30081ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void 30181ad6265SDimitry Andric__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, 30281ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx) { 30381ad6265SDimitry Andric formatter<_Tp, _CharT> __formatter; 30481ad6265SDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 30581ad6265SDimitry Andric // [format.string.std]/7 30681ad6265SDimitry Andric // ... If the corresponding formatting argument is not of integral type, or 30781ad6265SDimitry Andric // its value is negative for precision or non-positive for width, an 30881ad6265SDimitry Andric // exception of type format_error is thrown. 30981ad6265SDimitry Andric // 31081ad6265SDimitry Andric // Validate whether the arguments are integrals. 31181ad6265SDimitry Andric if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) { 31281ad6265SDimitry Andric // TODO FMT Remove this when parser v1 has been phased out. 31381ad6265SDimitry Andric if (__formatter.__width_needs_substitution()) 31481ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__width)); 31581ad6265SDimitry Andric 31681ad6265SDimitry Andric if constexpr (_HasPrecision) 31781ad6265SDimitry Andric if (__formatter.__precision_needs_substitution()) 31881ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision)); 31981ad6265SDimitry Andric } else { 32081ad6265SDimitry Andric if (__formatter.__parser_.__width_as_arg_) 32181ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); 32281ad6265SDimitry Andric 32381ad6265SDimitry Andric if constexpr (_HasPrecision) 32481ad6265SDimitry Andric if (__formatter.__parser_.__precision_as_arg_) 32581ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); 32681ad6265SDimitry Andric } 32781ad6265SDimitry Andric} 32881ad6265SDimitry Andric 32981ad6265SDimitry Andrictemplate <class _CharT> 33081ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx, 33181ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx, 33281ad6265SDimitry Andric __arg_t __type) { 33381ad6265SDimitry Andric switch (__type) { 33481ad6265SDimitry Andric case __arg_t::__none: 33581ad6265SDimitry Andric __throw_format_error("Invalid argument"); 33681ad6265SDimitry Andric case __arg_t::__boolean: 33781ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 33881ad6265SDimitry Andric case __arg_t::__char_type: 33981ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 34081ad6265SDimitry Andric case __arg_t::__int: 34181ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 34281ad6265SDimitry Andric case __arg_t::__long_long: 34381ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 34481ad6265SDimitry Andric case __arg_t::__i128: 34581ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 34681ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 34781ad6265SDimitry Andric# else 34881ad6265SDimitry Andric __throw_format_error("Invalid argument"); 34981ad6265SDimitry Andric# endif 35081ad6265SDimitry Andric return; 35181ad6265SDimitry Andric case __arg_t::__unsigned: 35281ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 35381ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 35481ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 35581ad6265SDimitry Andric case __arg_t::__u128: 35681ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 35781ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 35881ad6265SDimitry Andric# else 35981ad6265SDimitry Andric __throw_format_error("Invalid argument"); 36081ad6265SDimitry Andric# endif 36181ad6265SDimitry Andric return; 36281ad6265SDimitry Andric case __arg_t::__float: 36381ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 36481ad6265SDimitry Andric case __arg_t::__double: 36581ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 36681ad6265SDimitry Andric case __arg_t::__long_double: 36781ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 36881ad6265SDimitry Andric case __arg_t::__const_char_type_ptr: 36981ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 37081ad6265SDimitry Andric case __arg_t::__string_view: 37181ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 37281ad6265SDimitry Andric case __arg_t::__ptr: 37381ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 37481ad6265SDimitry Andric case __arg_t::__handle: 37581ad6265SDimitry Andric __throw_format_error("Handle should use __compile_time_validate_handle_argument"); 37681ad6265SDimitry Andric } 37781ad6265SDimitry Andric __throw_format_error("Invalid argument"); 37881ad6265SDimitry Andric} 37981ad6265SDimitry Andric 380349cc55cSDimitry Andrictemplate <class _CharT, class _ParseCtx, class _Ctx> 38181ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 382349cc55cSDimitry Andric__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 383349cc55cSDimitry Andric _ParseCtx& __parse_ctx, _Ctx& __ctx) { 384349cc55cSDimitry Andric __format::__parse_number_result __r = 385349cc55cSDimitry Andric __format::__parse_arg_id(__begin, __end, __parse_ctx); 386349cc55cSDimitry Andric 387753f127fSDimitry Andric bool __parse = *__r.__ptr == _CharT(':'); 388349cc55cSDimitry Andric switch (*__r.__ptr) { 389349cc55cSDimitry Andric case _CharT(':'): 390349cc55cSDimitry Andric // The arg-id has a format-specifier, advance the input to the format-spec. 391349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr + 1); 392349cc55cSDimitry Andric break; 393349cc55cSDimitry Andric case _CharT('}'): 394349cc55cSDimitry Andric // The arg-id has no format-specifier. 395349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr); 396349cc55cSDimitry Andric break; 397349cc55cSDimitry Andric default: 398349cc55cSDimitry Andric __throw_format_error( 399349cc55cSDimitry Andric "The replacement field arg-id should terminate at a ':' or '}'"); 400349cc55cSDimitry Andric } 401349cc55cSDimitry Andric 40281ad6265SDimitry Andric if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 40381ad6265SDimitry Andric __arg_t __type = __ctx.arg(__r.__value); 40481ad6265SDimitry Andric if (__type == __arg_t::__handle) 40581ad6265SDimitry Andric __ctx.__handle(__r.__value).__parse(__parse_ctx); 40681ad6265SDimitry Andric else 40781ad6265SDimitry Andric __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 40881ad6265SDimitry Andric } else 409349cc55cSDimitry Andric _VSTD::visit_format_arg( 410349cc55cSDimitry Andric [&](auto __arg) { 411349cc55cSDimitry Andric if constexpr (same_as<decltype(__arg), monostate>) 412349cc55cSDimitry Andric __throw_format_error("Argument index out of bounds"); 41304eeddc0SDimitry Andric else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 41404eeddc0SDimitry Andric __arg.format(__parse_ctx, __ctx); 415349cc55cSDimitry Andric else { 416349cc55cSDimitry Andric formatter<decltype(__arg), _CharT> __formatter; 417753f127fSDimitry Andric if (__parse) 418349cc55cSDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 419349cc55cSDimitry Andric __ctx.advance_to(__formatter.format(__arg, __ctx)); 420349cc55cSDimitry Andric } 421349cc55cSDimitry Andric }, 422349cc55cSDimitry Andric __ctx.arg(__r.__value)); 423349cc55cSDimitry Andric 424349cc55cSDimitry Andric __begin = __parse_ctx.begin(); 425349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 426349cc55cSDimitry Andric __throw_format_error("The replacement field misses a terminating '}'"); 427349cc55cSDimitry Andric 428349cc55cSDimitry Andric return ++__begin; 429349cc55cSDimitry Andric} 430349cc55cSDimitry Andric 431349cc55cSDimitry Andrictemplate <class _ParseCtx, class _Ctx> 43281ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator 433349cc55cSDimitry Andric__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 434349cc55cSDimitry Andric using _CharT = typename _ParseCtx::char_type; 435349cc55cSDimitry Andric static_assert(same_as<typename _Ctx::char_type, _CharT>); 436349cc55cSDimitry Andric 437349cc55cSDimitry Andric const _CharT* __begin = __parse_ctx.begin(); 438349cc55cSDimitry Andric const _CharT* __end = __parse_ctx.end(); 439349cc55cSDimitry Andric typename _Ctx::iterator __out_it = __ctx.out(); 440349cc55cSDimitry Andric while (__begin != __end) { 441349cc55cSDimitry Andric switch (*__begin) { 442349cc55cSDimitry Andric case _CharT('{'): 443349cc55cSDimitry Andric ++__begin; 444349cc55cSDimitry Andric if (__begin == __end) 445349cc55cSDimitry Andric __throw_format_error("The format string terminates at a '{'"); 446349cc55cSDimitry Andric 447349cc55cSDimitry Andric if (*__begin != _CharT('{')) [[likely]] { 448349cc55cSDimitry Andric __ctx.advance_to(_VSTD::move(__out_it)); 449349cc55cSDimitry Andric __begin = 450349cc55cSDimitry Andric __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 451349cc55cSDimitry Andric __out_it = __ctx.out(); 452349cc55cSDimitry Andric 453349cc55cSDimitry Andric // The output is written and __begin points to the next character. So 454349cc55cSDimitry Andric // start the next iteration. 455349cc55cSDimitry Andric continue; 456349cc55cSDimitry Andric } 457349cc55cSDimitry Andric // The string is an escape character. 458349cc55cSDimitry Andric break; 459349cc55cSDimitry Andric 460349cc55cSDimitry Andric case _CharT('}'): 461349cc55cSDimitry Andric ++__begin; 462349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 463349cc55cSDimitry Andric __throw_format_error( 464349cc55cSDimitry Andric "The format string contains an invalid escape sequence"); 465349cc55cSDimitry Andric 466349cc55cSDimitry Andric break; 467349cc55cSDimitry Andric } 468349cc55cSDimitry Andric 469349cc55cSDimitry Andric // Copy the character to the output verbatim. 470349cc55cSDimitry Andric *__out_it++ = *__begin++; 471349cc55cSDimitry Andric } 472349cc55cSDimitry Andric return __out_it; 473349cc55cSDimitry Andric} 474349cc55cSDimitry Andric 475349cc55cSDimitry Andric} // namespace __format 476349cc55cSDimitry Andric 47781ad6265SDimitry Andrictemplate <class _CharT, class... _Args> 478*61cfbce3SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS basic_format_string { 47981ad6265SDimitry Andric template <class _Tp> 48081ad6265SDimitry Andric requires convertible_to<const _Tp&, basic_string_view<_CharT>> 481*61cfbce3SDimitry Andric consteval basic_format_string(const _Tp& __str) : __str_{__str} { 48281ad6265SDimitry Andric __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 48381ad6265SDimitry Andric _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 48481ad6265SDimitry Andric } 48581ad6265SDimitry Andric 486*61cfbce3SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { 487*61cfbce3SDimitry Andric return __str_; 488*61cfbce3SDimitry Andric } 489*61cfbce3SDimitry Andric 49081ad6265SDimitry Andricprivate: 491*61cfbce3SDimitry Andric basic_string_view<_CharT> __str_; 492*61cfbce3SDimitry Andric 49381ad6265SDimitry Andric using _Context = __format::__compile_time_basic_format_context<_CharT>; 49481ad6265SDimitry Andric 49581ad6265SDimitry Andric static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 49681ad6265SDimitry Andric __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 49781ad6265SDimitry Andric 49881ad6265SDimitry Andric // TODO FMT remove this work-around when the AIX ICE has been resolved. 49981ad6265SDimitry Andric# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 50081ad6265SDimitry Andric template <class _Tp> 50181ad6265SDimitry Andric static constexpr __format::__compile_time_handle<_CharT> __get_handle() { 50281ad6265SDimitry Andric __format::__compile_time_handle<_CharT> __handle; 50381ad6265SDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 50481ad6265SDimitry Andric __handle.template __enable<_Tp>(); 50581ad6265SDimitry Andric 50681ad6265SDimitry Andric return __handle; 50781ad6265SDimitry Andric } 50881ad6265SDimitry Andric 50981ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ 51081ad6265SDimitry Andric __get_handle<_Args>()...}; 51181ad6265SDimitry Andric# else 51281ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 51381ad6265SDimitry Andric using _Tp = remove_cvref_t<_Args>; 51481ad6265SDimitry Andric __format::__compile_time_handle<_CharT> __handle; 51581ad6265SDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 51681ad6265SDimitry Andric __handle.template __enable<_Tp>(); 51781ad6265SDimitry Andric 51881ad6265SDimitry Andric return __handle; 51981ad6265SDimitry Andric }()...}; 52081ad6265SDimitry Andric# endif 52181ad6265SDimitry Andric}; 52281ad6265SDimitry Andric 52381ad6265SDimitry Andrictemplate <class... _Args> 524*61cfbce3SDimitry Andricusing format_string = basic_format_string<char, type_identity_t<_Args>...>; 52581ad6265SDimitry Andric 52681ad6265SDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 52781ad6265SDimitry Andrictemplate <class... _Args> 528*61cfbce3SDimitry Andricusing wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; 52981ad6265SDimitry Andric#endif 53081ad6265SDimitry Andric 5314824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 532349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 5334824e7fdSDimitry Andric __vformat_to( 5344824e7fdSDimitry Andric _OutIt __out_it, basic_string_view<_CharT> __fmt, 5354824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 5364824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 5374824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 538349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 539349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 5404824e7fdSDimitry Andric else { 54181ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 5424824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 5434824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 54481ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 54581ad6265SDimitry Andric __args)); 54681ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 5474824e7fdSDimitry Andric } 548349cc55cSDimitry Andric} 549349cc55cSDimitry Andric 55081ad6265SDimitry Andric// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 55181ad6265SDimitry Andric// https://reviews.llvm.org/D110499#inline-1180704 55281ad6265SDimitry Andric// TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 553349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 5544824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5554824e7fdSDimitry Andricvformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 556349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 557349cc55cSDimitry Andric} 558349cc55cSDimitry Andric 559349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 560349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 5614824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5624824e7fdSDimitry Andricvformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 563349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 564349cc55cSDimitry Andric} 565349cc55cSDimitry Andric#endif 566349cc55cSDimitry Andric 567349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 5684824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 569*61cfbce3SDimitry Andricformat_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { 570*61cfbce3SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), 5714824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 572349cc55cSDimitry Andric} 573349cc55cSDimitry Andric 574349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 575349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 5764824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 577*61cfbce3SDimitry Andricformat_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { 578*61cfbce3SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), 5794824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 580349cc55cSDimitry Andric} 581349cc55cSDimitry Andric#endif 582349cc55cSDimitry Andric 5834824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 584349cc55cSDimitry Andricvformat(string_view __fmt, format_args __args) { 585349cc55cSDimitry Andric string __res; 586349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 587349cc55cSDimitry Andric return __res; 588349cc55cSDimitry Andric} 589349cc55cSDimitry Andric 590349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 5914824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 592349cc55cSDimitry Andricvformat(wstring_view __fmt, wformat_args __args) { 593349cc55cSDimitry Andric wstring __res; 594349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 595349cc55cSDimitry Andric return __res; 596349cc55cSDimitry Andric} 597349cc55cSDimitry Andric#endif 598349cc55cSDimitry Andric 599349cc55cSDimitry Andrictemplate <class... _Args> 600*61cfbce3SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, 601753f127fSDimitry Andric _Args&&... __args) { 602*61cfbce3SDimitry Andric return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); 603349cc55cSDimitry Andric} 604349cc55cSDimitry Andric 605349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 606349cc55cSDimitry Andrictemplate <class... _Args> 6074824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 608*61cfbce3SDimitry Andricformat(wformat_string<_Args...> __fmt, _Args&&... __args) { 609*61cfbce3SDimitry Andric return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); 610349cc55cSDimitry Andric} 611349cc55cSDimitry Andric#endif 612349cc55cSDimitry Andric 61381ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 61481ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 61581ad6265SDimitry Andric basic_string_view<_CharT> __fmt, 61681ad6265SDimitry Andric basic_format_args<_Context> __args) { 61781ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 61881ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 61981ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 62081ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 62181ad6265SDimitry Andric} 62281ad6265SDimitry Andric 623349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 62481ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 625*61cfbce3SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { 626*61cfbce3SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); 627349cc55cSDimitry Andric} 628349cc55cSDimitry Andric 629349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 630349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 631349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 632*61cfbce3SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, 633753f127fSDimitry Andric _Args&&... __args) { 634*61cfbce3SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); 635349cc55cSDimitry Andric} 636349cc55cSDimitry Andric#endif 637349cc55cSDimitry Andric 63881ad6265SDimitry Andrictemplate <class _CharT> 63981ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 64081ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 64181ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 64281ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 64381ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 64481ad6265SDimitry Andric} 64581ad6265SDimitry Andric 646349cc55cSDimitry Andrictemplate <class... _Args> 64781ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 648*61cfbce3SDimitry Andricformatted_size(format_string<_Args...> __fmt, _Args&&... __args) { 649*61cfbce3SDimitry Andric return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); 650349cc55cSDimitry Andric} 651349cc55cSDimitry Andric 652349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 653349cc55cSDimitry Andrictemplate <class... _Args> 65481ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 655*61cfbce3SDimitry Andricformatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { 656*61cfbce3SDimitry Andric return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); 657349cc55cSDimitry Andric} 658349cc55cSDimitry Andric#endif 659349cc55cSDimitry Andric 660349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION 661349cc55cSDimitry Andric 6624824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 663349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 6644824e7fdSDimitry Andric __vformat_to( 6654824e7fdSDimitry Andric _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 6664824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 6674824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 6684824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 669349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 670349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 671349cc55cSDimitry Andric _VSTD::move(__loc))); 6724824e7fdSDimitry Andric else { 67381ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 6744824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 6754824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 67681ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 67781ad6265SDimitry Andric __args, _VSTD::move(__loc))); 67881ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 6794824e7fdSDimitry Andric } 680349cc55cSDimitry Andric} 681349cc55cSDimitry Andric 682349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 6834824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6844824e7fdSDimitry Andric _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 685349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 686349cc55cSDimitry Andric __args); 687349cc55cSDimitry Andric} 688349cc55cSDimitry Andric 689349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 690349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 6914824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6924824e7fdSDimitry Andric _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 693349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 694349cc55cSDimitry Andric __args); 695349cc55cSDimitry Andric} 696349cc55cSDimitry Andric#endif 697349cc55cSDimitry Andric 698349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 69981ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 700*61cfbce3SDimitry Andricformat_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 701*61cfbce3SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), 7024824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 703349cc55cSDimitry Andric} 704349cc55cSDimitry Andric 705349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 706349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 70781ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 708*61cfbce3SDimitry Andricformat_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 709*61cfbce3SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), 7104824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 711349cc55cSDimitry Andric} 712349cc55cSDimitry Andric#endif 713349cc55cSDimitry Andric 7144824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 715349cc55cSDimitry Andricvformat(locale __loc, string_view __fmt, format_args __args) { 716349cc55cSDimitry Andric string __res; 717349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 718349cc55cSDimitry Andric __args); 719349cc55cSDimitry Andric return __res; 720349cc55cSDimitry Andric} 721349cc55cSDimitry Andric 722349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 7234824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 724349cc55cSDimitry Andricvformat(locale __loc, wstring_view __fmt, wformat_args __args) { 725349cc55cSDimitry Andric wstring __res; 726349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 727349cc55cSDimitry Andric __args); 728349cc55cSDimitry Andric return __res; 729349cc55cSDimitry Andric} 730349cc55cSDimitry Andric#endif 731349cc55cSDimitry Andric 732349cc55cSDimitry Andrictemplate <class... _Args> 73381ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, 734*61cfbce3SDimitry Andric format_string<_Args...> __fmt, 735753f127fSDimitry Andric _Args&&... __args) { 736*61cfbce3SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), 737349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 738349cc55cSDimitry Andric} 739349cc55cSDimitry Andric 740349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 741349cc55cSDimitry Andrictemplate <class... _Args> 7424824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 743*61cfbce3SDimitry Andricformat(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 744*61cfbce3SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), 745349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 746349cc55cSDimitry Andric} 747349cc55cSDimitry Andric#endif 748349cc55cSDimitry Andric 74981ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 75081ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 75181ad6265SDimitry Andric locale __loc, basic_string_view<_CharT> __fmt, 75281ad6265SDimitry Andric basic_format_args<_Context> __args) { 75381ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 75481ad6265SDimitry Andric _VSTD::__format::__vformat_to( 75581ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 75681ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 75781ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 75881ad6265SDimitry Andric} 75981ad6265SDimitry Andric 760349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 76181ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 762*61cfbce3SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, 763753f127fSDimitry Andric _Args&&... __args) { 764*61cfbce3SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), 765349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 766349cc55cSDimitry Andric} 767349cc55cSDimitry Andric 768349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 769349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 77081ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 771*61cfbce3SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, 772753f127fSDimitry Andric _Args&&... __args) { 773*61cfbce3SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), 774349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 775349cc55cSDimitry Andric} 776349cc55cSDimitry Andric#endif 777349cc55cSDimitry Andric 77881ad6265SDimitry Andrictemplate <class _CharT> 77981ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 78081ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 78181ad6265SDimitry Andric _VSTD::__format::__vformat_to( 78281ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 78381ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 78481ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 78581ad6265SDimitry Andric} 78681ad6265SDimitry Andric 787349cc55cSDimitry Andrictemplate <class... _Args> 78881ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 789*61cfbce3SDimitry Andricformatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 790*61cfbce3SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); 791349cc55cSDimitry Andric} 792349cc55cSDimitry Andric 793349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 794349cc55cSDimitry Andrictemplate <class... _Args> 79581ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 796*61cfbce3SDimitry Andricformatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 797*61cfbce3SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); 798349cc55cSDimitry Andric} 799349cc55cSDimitry Andric#endif 800349cc55cSDimitry Andric 801349cc55cSDimitry Andric#endif // _LIBCPP_HAS_NO_LOCALIZATION 802349cc55cSDimitry Andric 803fe6060f1SDimitry Andric#endif //_LIBCPP_STD_VER > 17 804fe6060f1SDimitry Andric 805fe6060f1SDimitry Andric_LIBCPP_END_NAMESPACE_STD 806fe6060f1SDimitry Andric 8076e75b2fbSDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 8086e75b2fbSDimitry Andric 809fe6060f1SDimitry Andric#endif // _LIBCPP_FORMAT 810