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 2681ad6265SDimitry Andric // [format.fmt.string], class template basic-format-string 2781ad6265SDimitry Andric template<class charT, class... Args> 2881ad6265SDimitry Andric struct basic-format-string; // exposition only 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric template<class... Args> 3181ad6265SDimitry Andric using format-string = // exposition only 3281ad6265SDimitry Andric basic-format-string<char, type_identity_t<Args>...>; 3381ad6265SDimitry Andric template<class... Args> 3481ad6265SDimitry Andric using wformat-string = // exposition only 3581ad6265SDimitry Andric basic-format-string<wchar_t, type_identity_t<Args>...>; 3681ad6265SDimitry Andric 37349cc55cSDimitry Andric // [format.functions], formatting functions 38349cc55cSDimitry Andric template<class... Args> 39753f127fSDimitry Andric string format(format-string<Args...> fmt, Args&&... args); 40349cc55cSDimitry Andric template<class... Args> 41753f127fSDimitry Andric wstring format(wformat-string<Args...> fmt, Args&&... args); 42349cc55cSDimitry Andric template<class... Args> 43753f127fSDimitry Andric string format(const locale& loc, format-string<Args...> fmt, Args&&... args); 44349cc55cSDimitry Andric template<class... Args> 45753f127fSDimitry Andric wstring format(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 46349cc55cSDimitry Andric 47349cc55cSDimitry Andric string vformat(string_view fmt, format_args args); 48349cc55cSDimitry Andric wstring vformat(wstring_view fmt, wformat_args args); 49349cc55cSDimitry Andric string vformat(const locale& loc, string_view fmt, format_args args); 50349cc55cSDimitry Andric wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); 51349cc55cSDimitry Andric 52349cc55cSDimitry Andric template<class Out, class... Args> 53753f127fSDimitry Andric Out format_to(Out out, format-string<Args...> fmt, Args&&... args); 54349cc55cSDimitry Andric template<class Out, class... Args> 55753f127fSDimitry Andric Out format_to(Out out, wformat-string<Args...> fmt, Args&&... args); 56349cc55cSDimitry Andric template<class Out, class... Args> 57753f127fSDimitry Andric Out format_to(Out out, const locale& loc, format-string<Args...> fmt, Args&&... args); 58349cc55cSDimitry Andric template<class Out, class... Args> 59753f127fSDimitry Andric Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, Args&&... args); 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric template<class Out> 624824e7fdSDimitry Andric Out vformat_to(Out out, string_view fmt, format_args args); 63349cc55cSDimitry Andric template<class Out> 644824e7fdSDimitry Andric Out vformat_to(Out out, wstring_view fmt, wformat_args args); 65349cc55cSDimitry Andric template<class Out> 66349cc55cSDimitry Andric Out vformat_to(Out out, const locale& loc, string_view fmt, 674824e7fdSDimitry Andric format_args char> args); 68349cc55cSDimitry Andric template<class Out> 69349cc55cSDimitry Andric Out vformat_to(Out out, const locale& loc, wstring_view fmt, 704824e7fdSDimitry Andric wformat_args args); 71349cc55cSDimitry Andric 72349cc55cSDimitry Andric template<class Out> struct format_to_n_result { 73349cc55cSDimitry Andric Out out; 74349cc55cSDimitry Andric iter_difference_t<Out> size; 75349cc55cSDimitry Andric }; 76349cc55cSDimitry Andric template<class Out, class... Args> 77349cc55cSDimitry Andric format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 78753f127fSDimitry Andric format-string<Args...> fmt, Args&&... args); 79349cc55cSDimitry Andric template<class Out, class... Args> 80349cc55cSDimitry Andric format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 81753f127fSDimitry Andric wformat-string<Args...> fmt, Args&&... args); 82349cc55cSDimitry Andric template<class Out, class... Args> 83349cc55cSDimitry Andric format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 8481ad6265SDimitry Andric const locale& loc, format-string<Args...> fmt, 85753f127fSDimitry Andric 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, 8881ad6265SDimitry Andric const locale& loc, wformat-string<Args...> fmt, 89753f127fSDimitry Andric Args&&... args); 90349cc55cSDimitry Andric 91349cc55cSDimitry Andric template<class... Args> 92753f127fSDimitry Andric size_t formatted_size(format-string<Args...> fmt, Args&&... args); 93349cc55cSDimitry Andric template<class... Args> 94753f127fSDimitry Andric size_t formatted_size(wformat-string<Args...> fmt, Args&&... args); 95349cc55cSDimitry Andric template<class... Args> 96753f127fSDimitry Andric size_t formatted_size(const locale& loc, format-string<Args...> fmt, Args&&... args); 97349cc55cSDimitry Andric template<class... Args> 98753f127fSDimitry Andric size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 99349cc55cSDimitry Andric 100349cc55cSDimitry Andric // [format.formatter], formatter 10104eeddc0SDimitry Andric template<class T, class charT = char> struct formatter; 102349cc55cSDimitry Andric 103349cc55cSDimitry Andric // [format.parse.ctx], class template basic_format_parse_context 10404eeddc0SDimitry Andric template<class charT> class basic_format_parse_context; 105349cc55cSDimitry Andric using format_parse_context = basic_format_parse_context<char>; 106349cc55cSDimitry Andric using wformat_parse_context = basic_format_parse_context<wchar_t>; 107349cc55cSDimitry Andric 108349cc55cSDimitry Andric // [format.arguments], arguments 109349cc55cSDimitry Andric // [format.arg], class template basic_format_arg 11004eeddc0SDimitry Andric template<class Context> class basic_format_arg; 111349cc55cSDimitry Andric 112349cc55cSDimitry Andric template<class Visitor, class Context> 113349cc55cSDimitry Andric see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); 114349cc55cSDimitry Andric 115349cc55cSDimitry Andric // [format.arg.store], class template format-arg-store 11604eeddc0SDimitry Andric template<class Context, class... Args> struct format-arg-store; // exposition only 117349cc55cSDimitry Andric 118349cc55cSDimitry Andric template<class Context = format_context, class... Args> 119349cc55cSDimitry Andric format-arg-store<Context, Args...> 120753f127fSDimitry Andric make_format_args(Args&&... args); 121349cc55cSDimitry Andric template<class... Args> 122349cc55cSDimitry Andric format-arg-store<wformat_context, Args...> 123753f127fSDimitry Andric make_wformat_args(Args&&... args); 124349cc55cSDimitry Andric 125fe6060f1SDimitry Andric // [format.error], class format_error 12604eeddc0SDimitry Andric class format_error; 127fe6060f1SDimitry Andric} 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric*/ 130fe6060f1SDimitry Andric 13181ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler 132349cc55cSDimitry Andric// Make sure all feature-test macros are available. 1336e75b2fbSDimitry Andric#include <version> 134*fcaf7f86SDimitry Andric// Enable the contents of the header only when libc++ was built with experimental features enabled. 1356e75b2fbSDimitry Andric#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 1366e75b2fbSDimitry Andric 13781ad6265SDimitry Andric#include <__algorithm/clamp.h> 138fe6060f1SDimitry Andric#include <__config> 139349cc55cSDimitry Andric#include <__debug> 14081ad6265SDimitry Andric#include <__format/buffer.h> 14181ad6265SDimitry Andric#include <__format/concepts.h> 14281ad6265SDimitry Andric#include <__format/enable_insertable.h> 143349cc55cSDimitry Andric#include <__format/format_arg.h> 14481ad6265SDimitry Andric#include <__format/format_arg_store.h> 145349cc55cSDimitry Andric#include <__format/format_args.h> 146349cc55cSDimitry Andric#include <__format/format_context.h> 147fe6060f1SDimitry Andric#include <__format/format_error.h> 148349cc55cSDimitry Andric#include <__format/format_fwd.h> 149fe6060f1SDimitry Andric#include <__format/format_parse_context.h> 150349cc55cSDimitry Andric#include <__format/format_string.h> 151349cc55cSDimitry Andric#include <__format/format_to_n_result.h> 152349cc55cSDimitry Andric#include <__format/formatter.h> 153349cc55cSDimitry Andric#include <__format/formatter_bool.h> 154349cc55cSDimitry Andric#include <__format/formatter_char.h> 15504eeddc0SDimitry Andric#include <__format/formatter_floating_point.h> 156349cc55cSDimitry Andric#include <__format/formatter_integer.h> 15704eeddc0SDimitry Andric#include <__format/formatter_pointer.h> 158349cc55cSDimitry Andric#include <__format/formatter_string.h> 159349cc55cSDimitry Andric#include <__format/parser_std_format_spec.h> 160*fcaf7f86SDimitry Andric#include <__format/unicode.h> 16181ad6265SDimitry Andric#include <__iterator/back_insert_iterator.h> 16281ad6265SDimitry Andric#include <__iterator/incrementable_traits.h> 163349cc55cSDimitry Andric#include <__variant/monostate.h> 164349cc55cSDimitry Andric#include <array> 165349cc55cSDimitry Andric#include <concepts> 166349cc55cSDimitry Andric#include <string> 167349cc55cSDimitry Andric#include <string_view> 168349cc55cSDimitry Andric#include <type_traits> 169349cc55cSDimitry Andric 170349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION 171349cc55cSDimitry Andric#include <locale> 172349cc55cSDimitry Andric#endif 173fe6060f1SDimitry Andric 174fe6060f1SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 175fe6060f1SDimitry Andric# pragma GCC system_header 176fe6060f1SDimitry Andric#endif 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 179fe6060f1SDimitry Andric 180fe6060f1SDimitry Andric#if _LIBCPP_STD_VER > 17 181fe6060f1SDimitry Andric 182349cc55cSDimitry Andric// TODO FMT Move the implementation in this file to its own granular headers. 183349cc55cSDimitry Andric 184349cc55cSDimitry Andric// TODO FMT Evaluate which templates should be external templates. This 185349cc55cSDimitry Andric// improves the efficiency of the header. However since the header is still 186349cc55cSDimitry Andric// under heavy development and not all classes are stable it makes no sense 187349cc55cSDimitry Andric// to do this optimization now. 188349cc55cSDimitry Andric 189349cc55cSDimitry Andricusing format_args = basic_format_args<format_context>; 190349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 191349cc55cSDimitry Andricusing wformat_args = basic_format_args<wformat_context>; 192349cc55cSDimitry Andric#endif 193349cc55cSDimitry Andric 19481ad6265SDimitry Andrictemplate <class _Context = format_context, class... _Args> 195753f127fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { 196753f127fSDimitry Andric return _VSTD::__format_arg_store<_Context, _Args...>(__args...); 197349cc55cSDimitry Andric} 198349cc55cSDimitry Andric 199349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 200349cc55cSDimitry Andrictemplate <class... _Args> 201753f127fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) { 202753f127fSDimitry Andric return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...); 203349cc55cSDimitry Andric} 204349cc55cSDimitry Andric#endif 205349cc55cSDimitry Andric 206349cc55cSDimitry Andricnamespace __format { 207349cc55cSDimitry Andric 20881ad6265SDimitry Andric/// Helper class parse and handle argument. 20981ad6265SDimitry Andric/// 21081ad6265SDimitry Andric/// When parsing a handle which is not enabled the code is ill-formed. 21181ad6265SDimitry Andric/// This helper uses the parser of the appropriate formatter for the stored type. 21281ad6265SDimitry Andrictemplate <class _CharT> 21381ad6265SDimitry Andricclass _LIBCPP_TEMPLATE_VIS __compile_time_handle { 21481ad6265SDimitry Andricpublic: 21581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI 21681ad6265SDimitry Andric constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric template <class _Tp> 21981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 22081ad6265SDimitry Andric __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { 22181ad6265SDimitry Andric formatter<_Tp, _CharT> __f; 22281ad6265SDimitry Andric __parse_ctx.advance_to(__f.parse(__parse_ctx)); 22381ad6265SDimitry Andric }; 22481ad6265SDimitry Andric } 22581ad6265SDimitry Andric 22681ad6265SDimitry Andric // Before calling __parse the proper handler needs to be set with __enable. 22781ad6265SDimitry Andric // The default handler isn't a core constant expression. 22881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 22981ad6265SDimitry Andric : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {} 23081ad6265SDimitry Andric 23181ad6265SDimitry Andricprivate: 23281ad6265SDimitry Andric void (*__parse_)(basic_format_parse_context<_CharT>&); 23381ad6265SDimitry Andric}; 23481ad6265SDimitry Andric 23581ad6265SDimitry Andric// Dummy format_context only providing the parts used during constant 23681ad6265SDimitry Andric// validation of the basic-format-string. 23781ad6265SDimitry Andrictemplate <class _CharT> 23881ad6265SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 23981ad6265SDimitry Andricpublic: 24081ad6265SDimitry Andric using char_type = _CharT; 24181ad6265SDimitry Andric 24281ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 24381ad6265SDimitry Andric const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 24481ad6265SDimitry Andric : __args_(__args), __handles_(__handles), __size_(__size) {} 24581ad6265SDimitry Andric 24681ad6265SDimitry Andric // During the compile-time validation nothing needs to be written. 24781ad6265SDimitry Andric // Therefore all operations of this iterator are a NOP. 24881ad6265SDimitry Andric struct iterator { 24981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 25081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 25181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 25281ad6265SDimitry Andric }; 25381ad6265SDimitry Andric 25481ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 25581ad6265SDimitry Andric if (__id >= __size_) 25681ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 25781ad6265SDimitry Andric return __args_[__id]; 25881ad6265SDimitry Andric } 25981ad6265SDimitry Andric 26081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 26181ad6265SDimitry Andric if (__id >= __size_) 26281ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 26381ad6265SDimitry Andric return __handles_[__id]; 26481ad6265SDimitry Andric } 26581ad6265SDimitry Andric 26681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 26781ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 26881ad6265SDimitry Andric 26981ad6265SDimitry Andricprivate: 27081ad6265SDimitry Andric const __arg_t* __args_; 27181ad6265SDimitry Andric const __compile_time_handle<_CharT>* __handles_; 27281ad6265SDimitry Andric size_t __size_; 27381ad6265SDimitry Andric}; 27481ad6265SDimitry Andric 27581ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI 27681ad6265SDimitry Andricconstexpr void __compile_time_validate_integral(__arg_t __type) { 27781ad6265SDimitry Andric switch (__type) { 27881ad6265SDimitry Andric case __arg_t::__int: 27981ad6265SDimitry Andric case __arg_t::__long_long: 28081ad6265SDimitry Andric case __arg_t::__i128: 28181ad6265SDimitry Andric case __arg_t::__unsigned: 28281ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 28381ad6265SDimitry Andric case __arg_t::__u128: 28481ad6265SDimitry Andric return; 28581ad6265SDimitry Andric 28681ad6265SDimitry Andric default: 28781ad6265SDimitry Andric __throw_format_error("Argument isn't an integral type"); 28881ad6265SDimitry Andric } 28981ad6265SDimitry Andric} 29081ad6265SDimitry Andric 29181ad6265SDimitry Andric// _HasPrecision does the formatter have a precision? 29281ad6265SDimitry Andrictemplate <class _CharT, class _Tp, bool _HasPrecision = false> 29381ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void 29481ad6265SDimitry Andric__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, 29581ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx) { 29681ad6265SDimitry Andric formatter<_Tp, _CharT> __formatter; 29781ad6265SDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 29881ad6265SDimitry Andric // [format.string.std]/7 29981ad6265SDimitry Andric // ... If the corresponding formatting argument is not of integral type, or 30081ad6265SDimitry Andric // its value is negative for precision or non-positive for width, an 30181ad6265SDimitry Andric // exception of type format_error is thrown. 30281ad6265SDimitry Andric // 30381ad6265SDimitry Andric // Validate whether the arguments are integrals. 30481ad6265SDimitry Andric if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) { 30581ad6265SDimitry Andric // TODO FMT Remove this when parser v1 has been phased out. 30681ad6265SDimitry Andric if (__formatter.__width_needs_substitution()) 30781ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__width)); 30881ad6265SDimitry Andric 30981ad6265SDimitry Andric if constexpr (_HasPrecision) 31081ad6265SDimitry Andric if (__formatter.__precision_needs_substitution()) 31181ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision)); 31281ad6265SDimitry Andric } else { 31381ad6265SDimitry Andric if (__formatter.__parser_.__width_as_arg_) 31481ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); 31581ad6265SDimitry Andric 31681ad6265SDimitry Andric if constexpr (_HasPrecision) 31781ad6265SDimitry Andric if (__formatter.__parser_.__precision_as_arg_) 31881ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); 31981ad6265SDimitry Andric } 32081ad6265SDimitry Andric} 32181ad6265SDimitry Andric 32281ad6265SDimitry Andrictemplate <class _CharT> 32381ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx, 32481ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx, 32581ad6265SDimitry Andric __arg_t __type) { 32681ad6265SDimitry Andric switch (__type) { 32781ad6265SDimitry Andric case __arg_t::__none: 32881ad6265SDimitry Andric __throw_format_error("Invalid argument"); 32981ad6265SDimitry Andric case __arg_t::__boolean: 33081ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 33181ad6265SDimitry Andric case __arg_t::__char_type: 33281ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 33381ad6265SDimitry Andric case __arg_t::__int: 33481ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 33581ad6265SDimitry Andric case __arg_t::__long_long: 33681ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 33781ad6265SDimitry Andric case __arg_t::__i128: 33881ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 33981ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 34081ad6265SDimitry Andric# else 34181ad6265SDimitry Andric __throw_format_error("Invalid argument"); 34281ad6265SDimitry Andric# endif 34381ad6265SDimitry Andric return; 34481ad6265SDimitry Andric case __arg_t::__unsigned: 34581ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 34681ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 34781ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 34881ad6265SDimitry Andric case __arg_t::__u128: 34981ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 35081ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 35181ad6265SDimitry Andric# else 35281ad6265SDimitry Andric __throw_format_error("Invalid argument"); 35381ad6265SDimitry Andric# endif 35481ad6265SDimitry Andric return; 35581ad6265SDimitry Andric case __arg_t::__float: 35681ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 35781ad6265SDimitry Andric case __arg_t::__double: 35881ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 35981ad6265SDimitry Andric case __arg_t::__long_double: 36081ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 36181ad6265SDimitry Andric case __arg_t::__const_char_type_ptr: 36281ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 36381ad6265SDimitry Andric case __arg_t::__string_view: 36481ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 36581ad6265SDimitry Andric case __arg_t::__ptr: 36681ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 36781ad6265SDimitry Andric case __arg_t::__handle: 36881ad6265SDimitry Andric __throw_format_error("Handle should use __compile_time_validate_handle_argument"); 36981ad6265SDimitry Andric } 37081ad6265SDimitry Andric __throw_format_error("Invalid argument"); 37181ad6265SDimitry Andric} 37281ad6265SDimitry Andric 373349cc55cSDimitry Andrictemplate <class _CharT, class _ParseCtx, class _Ctx> 37481ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 375349cc55cSDimitry Andric__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 376349cc55cSDimitry Andric _ParseCtx& __parse_ctx, _Ctx& __ctx) { 377349cc55cSDimitry Andric __format::__parse_number_result __r = 378349cc55cSDimitry Andric __format::__parse_arg_id(__begin, __end, __parse_ctx); 379349cc55cSDimitry Andric 380753f127fSDimitry Andric bool __parse = *__r.__ptr == _CharT(':'); 381349cc55cSDimitry Andric switch (*__r.__ptr) { 382349cc55cSDimitry Andric case _CharT(':'): 383349cc55cSDimitry Andric // The arg-id has a format-specifier, advance the input to the format-spec. 384349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr + 1); 385349cc55cSDimitry Andric break; 386349cc55cSDimitry Andric case _CharT('}'): 387349cc55cSDimitry Andric // The arg-id has no format-specifier. 388349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr); 389349cc55cSDimitry Andric break; 390349cc55cSDimitry Andric default: 391349cc55cSDimitry Andric __throw_format_error( 392349cc55cSDimitry Andric "The replacement field arg-id should terminate at a ':' or '}'"); 393349cc55cSDimitry Andric } 394349cc55cSDimitry Andric 39581ad6265SDimitry Andric if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 39681ad6265SDimitry Andric __arg_t __type = __ctx.arg(__r.__value); 39781ad6265SDimitry Andric if (__type == __arg_t::__handle) 39881ad6265SDimitry Andric __ctx.__handle(__r.__value).__parse(__parse_ctx); 39981ad6265SDimitry Andric else 40081ad6265SDimitry Andric __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 40181ad6265SDimitry Andric } else 402349cc55cSDimitry Andric _VSTD::visit_format_arg( 403349cc55cSDimitry Andric [&](auto __arg) { 404349cc55cSDimitry Andric if constexpr (same_as<decltype(__arg), monostate>) 405349cc55cSDimitry Andric __throw_format_error("Argument index out of bounds"); 40604eeddc0SDimitry Andric else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 40704eeddc0SDimitry Andric __arg.format(__parse_ctx, __ctx); 408349cc55cSDimitry Andric else { 409349cc55cSDimitry Andric formatter<decltype(__arg), _CharT> __formatter; 410753f127fSDimitry Andric if (__parse) 411349cc55cSDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 412349cc55cSDimitry Andric __ctx.advance_to(__formatter.format(__arg, __ctx)); 413349cc55cSDimitry Andric } 414349cc55cSDimitry Andric }, 415349cc55cSDimitry Andric __ctx.arg(__r.__value)); 416349cc55cSDimitry Andric 417349cc55cSDimitry Andric __begin = __parse_ctx.begin(); 418349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 419349cc55cSDimitry Andric __throw_format_error("The replacement field misses a terminating '}'"); 420349cc55cSDimitry Andric 421349cc55cSDimitry Andric return ++__begin; 422349cc55cSDimitry Andric} 423349cc55cSDimitry Andric 424349cc55cSDimitry Andrictemplate <class _ParseCtx, class _Ctx> 42581ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator 426349cc55cSDimitry Andric__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 427349cc55cSDimitry Andric using _CharT = typename _ParseCtx::char_type; 428349cc55cSDimitry Andric static_assert(same_as<typename _Ctx::char_type, _CharT>); 429349cc55cSDimitry Andric 430349cc55cSDimitry Andric const _CharT* __begin = __parse_ctx.begin(); 431349cc55cSDimitry Andric const _CharT* __end = __parse_ctx.end(); 432349cc55cSDimitry Andric typename _Ctx::iterator __out_it = __ctx.out(); 433349cc55cSDimitry Andric while (__begin != __end) { 434349cc55cSDimitry Andric switch (*__begin) { 435349cc55cSDimitry Andric case _CharT('{'): 436349cc55cSDimitry Andric ++__begin; 437349cc55cSDimitry Andric if (__begin == __end) 438349cc55cSDimitry Andric __throw_format_error("The format string terminates at a '{'"); 439349cc55cSDimitry Andric 440349cc55cSDimitry Andric if (*__begin != _CharT('{')) [[likely]] { 441349cc55cSDimitry Andric __ctx.advance_to(_VSTD::move(__out_it)); 442349cc55cSDimitry Andric __begin = 443349cc55cSDimitry Andric __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 444349cc55cSDimitry Andric __out_it = __ctx.out(); 445349cc55cSDimitry Andric 446349cc55cSDimitry Andric // The output is written and __begin points to the next character. So 447349cc55cSDimitry Andric // start the next iteration. 448349cc55cSDimitry Andric continue; 449349cc55cSDimitry Andric } 450349cc55cSDimitry Andric // The string is an escape character. 451349cc55cSDimitry Andric break; 452349cc55cSDimitry Andric 453349cc55cSDimitry Andric case _CharT('}'): 454349cc55cSDimitry Andric ++__begin; 455349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 456349cc55cSDimitry Andric __throw_format_error( 457349cc55cSDimitry Andric "The format string contains an invalid escape sequence"); 458349cc55cSDimitry Andric 459349cc55cSDimitry Andric break; 460349cc55cSDimitry Andric } 461349cc55cSDimitry Andric 462349cc55cSDimitry Andric // Copy the character to the output verbatim. 463349cc55cSDimitry Andric *__out_it++ = *__begin++; 464349cc55cSDimitry Andric } 465349cc55cSDimitry Andric return __out_it; 466349cc55cSDimitry Andric} 467349cc55cSDimitry Andric 468349cc55cSDimitry Andric} // namespace __format 469349cc55cSDimitry Andric 47081ad6265SDimitry Andrictemplate <class _CharT, class... _Args> 47181ad6265SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __basic_format_string { 47281ad6265SDimitry Andric basic_string_view<_CharT> __str_; 47381ad6265SDimitry Andric 47481ad6265SDimitry Andric template <class _Tp> 47581ad6265SDimitry Andric requires convertible_to<const _Tp&, basic_string_view<_CharT>> 47681ad6265SDimitry Andric consteval __basic_format_string(const _Tp& __str) : __str_{__str} { 47781ad6265SDimitry Andric __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 47881ad6265SDimitry Andric _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 47981ad6265SDimitry Andric } 48081ad6265SDimitry Andric 48181ad6265SDimitry Andricprivate: 48281ad6265SDimitry Andric using _Context = __format::__compile_time_basic_format_context<_CharT>; 48381ad6265SDimitry Andric 48481ad6265SDimitry Andric static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 48581ad6265SDimitry Andric __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 48681ad6265SDimitry Andric 48781ad6265SDimitry Andric // TODO FMT remove this work-around when the AIX ICE has been resolved. 48881ad6265SDimitry Andric# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 48981ad6265SDimitry Andric template <class _Tp> 49081ad6265SDimitry Andric static constexpr __format::__compile_time_handle<_CharT> __get_handle() { 49181ad6265SDimitry Andric __format::__compile_time_handle<_CharT> __handle; 49281ad6265SDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 49381ad6265SDimitry Andric __handle.template __enable<_Tp>(); 49481ad6265SDimitry Andric 49581ad6265SDimitry Andric return __handle; 49681ad6265SDimitry Andric } 49781ad6265SDimitry Andric 49881ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ 49981ad6265SDimitry Andric __get_handle<_Args>()...}; 50081ad6265SDimitry Andric# else 50181ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 50281ad6265SDimitry Andric using _Tp = remove_cvref_t<_Args>; 50381ad6265SDimitry Andric __format::__compile_time_handle<_CharT> __handle; 50481ad6265SDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 50581ad6265SDimitry Andric __handle.template __enable<_Tp>(); 50681ad6265SDimitry Andric 50781ad6265SDimitry Andric return __handle; 50881ad6265SDimitry Andric }()...}; 50981ad6265SDimitry Andric# endif 51081ad6265SDimitry Andric}; 51181ad6265SDimitry Andric 51281ad6265SDimitry Andrictemplate <class... _Args> 51381ad6265SDimitry Andricusing __format_string_t = __basic_format_string<char, type_identity_t<_Args>...>; 51481ad6265SDimitry Andric 51581ad6265SDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 51681ad6265SDimitry Andrictemplate <class... _Args> 51781ad6265SDimitry Andricusing __wformat_string_t = __basic_format_string<wchar_t, type_identity_t<_Args>...>; 51881ad6265SDimitry Andric#endif 51981ad6265SDimitry Andric 5204824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 521349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 5224824e7fdSDimitry Andric __vformat_to( 5234824e7fdSDimitry Andric _OutIt __out_it, basic_string_view<_CharT> __fmt, 5244824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 5254824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 5264824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 527349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 528349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 5294824e7fdSDimitry Andric else { 53081ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 5314824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 5324824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 53381ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 53481ad6265SDimitry Andric __args)); 53581ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 5364824e7fdSDimitry Andric } 537349cc55cSDimitry Andric} 538349cc55cSDimitry Andric 53981ad6265SDimitry Andric// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 54081ad6265SDimitry Andric// https://reviews.llvm.org/D110499#inline-1180704 54181ad6265SDimitry Andric// TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 542349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 5434824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5444824e7fdSDimitry Andricvformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 545349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 546349cc55cSDimitry Andric} 547349cc55cSDimitry Andric 548349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 549349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 5504824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5514824e7fdSDimitry Andricvformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 552349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 553349cc55cSDimitry Andric} 554349cc55cSDimitry Andric#endif 555349cc55cSDimitry Andric 556349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 5574824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 558753f127fSDimitry Andricformat_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, _Args&&... __args) { 55981ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, 5604824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 561349cc55cSDimitry Andric} 562349cc55cSDimitry Andric 563349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 564349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 5654824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 566753f127fSDimitry Andricformat_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 56781ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, 5684824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 569349cc55cSDimitry Andric} 570349cc55cSDimitry Andric#endif 571349cc55cSDimitry Andric 5724824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 573349cc55cSDimitry Andricvformat(string_view __fmt, format_args __args) { 574349cc55cSDimitry Andric string __res; 575349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 576349cc55cSDimitry Andric return __res; 577349cc55cSDimitry Andric} 578349cc55cSDimitry Andric 579349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 5804824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 581349cc55cSDimitry Andricvformat(wstring_view __fmt, wformat_args __args) { 582349cc55cSDimitry Andric wstring __res; 583349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 584349cc55cSDimitry Andric return __res; 585349cc55cSDimitry Andric} 586349cc55cSDimitry Andric#endif 587349cc55cSDimitry Andric 588349cc55cSDimitry Andrictemplate <class... _Args> 58981ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt, 590753f127fSDimitry Andric _Args&&... __args) { 59181ad6265SDimitry Andric return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...)); 592349cc55cSDimitry Andric} 593349cc55cSDimitry Andric 594349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 595349cc55cSDimitry Andrictemplate <class... _Args> 5964824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 597753f127fSDimitry Andricformat(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { 59881ad6265SDimitry Andric return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...)); 599349cc55cSDimitry Andric} 600349cc55cSDimitry Andric#endif 601349cc55cSDimitry Andric 60281ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 60381ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 60481ad6265SDimitry Andric basic_string_view<_CharT> __fmt, 60581ad6265SDimitry Andric basic_format_args<_Context> __args) { 60681ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 60781ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 60881ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 60981ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 61081ad6265SDimitry Andric} 61181ad6265SDimitry Andric 612349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 61381ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 614753f127fSDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, _Args&&... __args) { 61581ad6265SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...)); 616349cc55cSDimitry Andric} 617349cc55cSDimitry Andric 618349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 619349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 620349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 62181ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt, 622753f127fSDimitry Andric _Args&&... __args) { 62381ad6265SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...)); 624349cc55cSDimitry Andric} 625349cc55cSDimitry Andric#endif 626349cc55cSDimitry Andric 62781ad6265SDimitry Andrictemplate <class _CharT> 62881ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 62981ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 63081ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 63181ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 63281ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 63381ad6265SDimitry Andric} 63481ad6265SDimitry Andric 635349cc55cSDimitry Andrictemplate <class... _Args> 63681ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 637753f127fSDimitry Andricformatted_size(__format_string_t<_Args...> __fmt, _Args&&... __args) { 63881ad6265SDimitry Andric return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); 639349cc55cSDimitry Andric} 640349cc55cSDimitry Andric 641349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 642349cc55cSDimitry Andrictemplate <class... _Args> 64381ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 644753f127fSDimitry Andricformatted_size(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { 64581ad6265SDimitry Andric return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); 646349cc55cSDimitry Andric} 647349cc55cSDimitry Andric#endif 648349cc55cSDimitry Andric 649349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION 650349cc55cSDimitry Andric 6514824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 652349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 6534824e7fdSDimitry Andric __vformat_to( 6544824e7fdSDimitry Andric _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 6554824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 6564824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 6574824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 658349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 659349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 660349cc55cSDimitry Andric _VSTD::move(__loc))); 6614824e7fdSDimitry Andric else { 66281ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 6634824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 6644824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 66581ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 66681ad6265SDimitry Andric __args, _VSTD::move(__loc))); 66781ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 6684824e7fdSDimitry Andric } 669349cc55cSDimitry Andric} 670349cc55cSDimitry Andric 671349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 6724824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6734824e7fdSDimitry Andric _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 674349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 675349cc55cSDimitry Andric __args); 676349cc55cSDimitry Andric} 677349cc55cSDimitry Andric 678349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 679349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 6804824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6814824e7fdSDimitry Andric _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 682349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 683349cc55cSDimitry Andric __args); 684349cc55cSDimitry Andric} 685349cc55cSDimitry Andric#endif 686349cc55cSDimitry Andric 687349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 68881ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 689753f127fSDimitry Andricformat_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { 69081ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, 6914824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 692349cc55cSDimitry Andric} 693349cc55cSDimitry Andric 694349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 695349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 69681ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 697753f127fSDimitry Andricformat_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 69881ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, 6994824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 700349cc55cSDimitry Andric} 701349cc55cSDimitry Andric#endif 702349cc55cSDimitry Andric 7034824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 704349cc55cSDimitry Andricvformat(locale __loc, string_view __fmt, format_args __args) { 705349cc55cSDimitry Andric string __res; 706349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 707349cc55cSDimitry Andric __args); 708349cc55cSDimitry Andric return __res; 709349cc55cSDimitry Andric} 710349cc55cSDimitry Andric 711349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 7124824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 713349cc55cSDimitry Andricvformat(locale __loc, wstring_view __fmt, wformat_args __args) { 714349cc55cSDimitry Andric wstring __res; 715349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 716349cc55cSDimitry Andric __args); 717349cc55cSDimitry Andric return __res; 718349cc55cSDimitry Andric} 719349cc55cSDimitry Andric#endif 720349cc55cSDimitry Andric 721349cc55cSDimitry Andrictemplate <class... _Args> 72281ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, 72381ad6265SDimitry Andric __format_string_t<_Args...> __fmt, 724753f127fSDimitry Andric _Args&&... __args) { 72581ad6265SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, 726349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 727349cc55cSDimitry Andric} 728349cc55cSDimitry Andric 729349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 730349cc55cSDimitry Andrictemplate <class... _Args> 7314824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 732753f127fSDimitry Andricformat(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 73381ad6265SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, 734349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 735349cc55cSDimitry Andric} 736349cc55cSDimitry Andric#endif 737349cc55cSDimitry Andric 73881ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 73981ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 74081ad6265SDimitry Andric locale __loc, basic_string_view<_CharT> __fmt, 74181ad6265SDimitry Andric basic_format_args<_Context> __args) { 74281ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 74381ad6265SDimitry Andric _VSTD::__format::__vformat_to( 74481ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 74581ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 74681ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 74781ad6265SDimitry Andric} 74881ad6265SDimitry Andric 749349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 75081ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 75181ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt, 752753f127fSDimitry Andric _Args&&... __args) { 75381ad6265SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, 754349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 755349cc55cSDimitry Andric} 756349cc55cSDimitry Andric 757349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 758349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 75981ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 76081ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt, 761753f127fSDimitry Andric _Args&&... __args) { 76281ad6265SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, 763349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 764349cc55cSDimitry Andric} 765349cc55cSDimitry Andric#endif 766349cc55cSDimitry Andric 76781ad6265SDimitry Andrictemplate <class _CharT> 76881ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 76981ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 77081ad6265SDimitry Andric _VSTD::__format::__vformat_to( 77181ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 77281ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 77381ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 77481ad6265SDimitry Andric} 77581ad6265SDimitry Andric 776349cc55cSDimitry Andrictemplate <class... _Args> 77781ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 778753f127fSDimitry Andricformatted_size(locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { 77981ad6265SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); 780349cc55cSDimitry Andric} 781349cc55cSDimitry Andric 782349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 783349cc55cSDimitry Andrictemplate <class... _Args> 78481ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 785753f127fSDimitry Andricformatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 78681ad6265SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); 787349cc55cSDimitry Andric} 788349cc55cSDimitry Andric#endif 789349cc55cSDimitry Andric 790349cc55cSDimitry Andric#endif // _LIBCPP_HAS_NO_LOCALIZATION 791349cc55cSDimitry Andric 792fe6060f1SDimitry Andric#endif //_LIBCPP_STD_VER > 17 793fe6060f1SDimitry Andric 794fe6060f1SDimitry Andric_LIBCPP_END_NAMESPACE_STD 795fe6060f1SDimitry Andric 7966e75b2fbSDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 7976e75b2fbSDimitry Andric 798fe6060f1SDimitry Andric#endif // _LIBCPP_FORMAT 799