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> 39*753f127fSDimitry Andric string format(format-string<Args...> fmt, Args&&... args); 40349cc55cSDimitry Andric template<class... Args> 41*753f127fSDimitry Andric wstring format(wformat-string<Args...> fmt, Args&&... args); 42349cc55cSDimitry Andric template<class... Args> 43*753f127fSDimitry Andric string format(const locale& loc, format-string<Args...> fmt, Args&&... args); 44349cc55cSDimitry Andric template<class... Args> 45*753f127fSDimitry 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> 53*753f127fSDimitry Andric Out format_to(Out out, format-string<Args...> fmt, Args&&... args); 54349cc55cSDimitry Andric template<class Out, class... Args> 55*753f127fSDimitry Andric Out format_to(Out out, wformat-string<Args...> fmt, Args&&... args); 56349cc55cSDimitry Andric template<class Out, class... Args> 57*753f127fSDimitry Andric Out format_to(Out out, const locale& loc, format-string<Args...> fmt, Args&&... args); 58349cc55cSDimitry Andric template<class Out, class... Args> 59*753f127fSDimitry 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, 78*753f127fSDimitry 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, 81*753f127fSDimitry 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, 85*753f127fSDimitry 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, 89*753f127fSDimitry Andric Args&&... args); 90349cc55cSDimitry Andric 91349cc55cSDimitry Andric template<class... Args> 92*753f127fSDimitry Andric size_t formatted_size(format-string<Args...> fmt, Args&&... args); 93349cc55cSDimitry Andric template<class... Args> 94*753f127fSDimitry Andric size_t formatted_size(wformat-string<Args...> fmt, Args&&... args); 95349cc55cSDimitry Andric template<class... Args> 96*753f127fSDimitry Andric size_t formatted_size(const locale& loc, format-string<Args...> fmt, Args&&... args); 97349cc55cSDimitry Andric template<class... Args> 98*753f127fSDimitry 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...> 120*753f127fSDimitry Andric make_format_args(Args&&... args); 121349cc55cSDimitry Andric template<class... Args> 122349cc55cSDimitry Andric format-arg-store<wformat_context, Args...> 123*753f127fSDimitry 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> 134349cc55cSDimitry Andric// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES. 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> 16081ad6265SDimitry Andric#include <__iterator/back_insert_iterator.h> 16181ad6265SDimitry Andric#include <__iterator/incrementable_traits.h> 162349cc55cSDimitry Andric#include <__variant/monostate.h> 163349cc55cSDimitry Andric#include <array> 164349cc55cSDimitry Andric#include <concepts> 165349cc55cSDimitry Andric#include <string> 166349cc55cSDimitry Andric#include <string_view> 167349cc55cSDimitry Andric#include <type_traits> 168349cc55cSDimitry Andric 169349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION 170349cc55cSDimitry Andric#include <locale> 171349cc55cSDimitry Andric#endif 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 174fe6060f1SDimitry Andric# pragma GCC system_header 175fe6060f1SDimitry Andric#endif 176fe6060f1SDimitry Andric 177fe6060f1SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 178fe6060f1SDimitry Andric 179fe6060f1SDimitry Andric#if _LIBCPP_STD_VER > 17 180fe6060f1SDimitry Andric 181349cc55cSDimitry Andric// TODO FMT Move the implementation in this file to its own granular headers. 182349cc55cSDimitry Andric 183349cc55cSDimitry Andric// TODO FMT Evaluate which templates should be external templates. This 184349cc55cSDimitry Andric// improves the efficiency of the header. However since the header is still 185349cc55cSDimitry Andric// under heavy development and not all classes are stable it makes no sense 186349cc55cSDimitry Andric// to do this optimization now. 187349cc55cSDimitry Andric 188349cc55cSDimitry Andricusing format_args = basic_format_args<format_context>; 189349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 190349cc55cSDimitry Andricusing wformat_args = basic_format_args<wformat_context>; 191349cc55cSDimitry Andric#endif 192349cc55cSDimitry Andric 19381ad6265SDimitry Andrictemplate <class _Context = format_context, class... _Args> 194*753f127fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { 195*753f127fSDimitry Andric return _VSTD::__format_arg_store<_Context, _Args...>(__args...); 196349cc55cSDimitry Andric} 197349cc55cSDimitry Andric 198349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 199349cc55cSDimitry Andrictemplate <class... _Args> 200*753f127fSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) { 201*753f127fSDimitry Andric return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...); 202349cc55cSDimitry Andric} 203349cc55cSDimitry Andric#endif 204349cc55cSDimitry Andric 205349cc55cSDimitry Andricnamespace __format { 206349cc55cSDimitry Andric 20781ad6265SDimitry Andric/// Helper class parse and handle argument. 20881ad6265SDimitry Andric/// 20981ad6265SDimitry Andric/// When parsing a handle which is not enabled the code is ill-formed. 21081ad6265SDimitry Andric/// This helper uses the parser of the appropriate formatter for the stored type. 21181ad6265SDimitry Andrictemplate <class _CharT> 21281ad6265SDimitry Andricclass _LIBCPP_TEMPLATE_VIS __compile_time_handle { 21381ad6265SDimitry Andricpublic: 21481ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI 21581ad6265SDimitry Andric constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } 21681ad6265SDimitry Andric 21781ad6265SDimitry Andric template <class _Tp> 21881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 21981ad6265SDimitry Andric __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { 22081ad6265SDimitry Andric formatter<_Tp, _CharT> __f; 22181ad6265SDimitry Andric __parse_ctx.advance_to(__f.parse(__parse_ctx)); 22281ad6265SDimitry Andric }; 22381ad6265SDimitry Andric } 22481ad6265SDimitry Andric 22581ad6265SDimitry Andric // Before calling __parse the proper handler needs to be set with __enable. 22681ad6265SDimitry Andric // The default handler isn't a core constant expression. 22781ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 22881ad6265SDimitry Andric : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {} 22981ad6265SDimitry Andric 23081ad6265SDimitry Andricprivate: 23181ad6265SDimitry Andric void (*__parse_)(basic_format_parse_context<_CharT>&); 23281ad6265SDimitry Andric}; 23381ad6265SDimitry Andric 23481ad6265SDimitry Andric// Dummy format_context only providing the parts used during constant 23581ad6265SDimitry Andric// validation of the basic-format-string. 23681ad6265SDimitry Andrictemplate <class _CharT> 23781ad6265SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 23881ad6265SDimitry Andricpublic: 23981ad6265SDimitry Andric using char_type = _CharT; 24081ad6265SDimitry Andric 24181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 24281ad6265SDimitry Andric const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 24381ad6265SDimitry Andric : __args_(__args), __handles_(__handles), __size_(__size) {} 24481ad6265SDimitry Andric 24581ad6265SDimitry Andric // During the compile-time validation nothing needs to be written. 24681ad6265SDimitry Andric // Therefore all operations of this iterator are a NOP. 24781ad6265SDimitry Andric struct iterator { 24881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 24981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 25081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 25181ad6265SDimitry Andric }; 25281ad6265SDimitry Andric 25381ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 25481ad6265SDimitry Andric if (__id >= __size_) 25581ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 25681ad6265SDimitry Andric return __args_[__id]; 25781ad6265SDimitry Andric } 25881ad6265SDimitry Andric 25981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 26081ad6265SDimitry Andric if (__id >= __size_) 26181ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 26281ad6265SDimitry Andric return __handles_[__id]; 26381ad6265SDimitry Andric } 26481ad6265SDimitry Andric 26581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 26681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 26781ad6265SDimitry Andric 26881ad6265SDimitry Andricprivate: 26981ad6265SDimitry Andric const __arg_t* __args_; 27081ad6265SDimitry Andric const __compile_time_handle<_CharT>* __handles_; 27181ad6265SDimitry Andric size_t __size_; 27281ad6265SDimitry Andric}; 27381ad6265SDimitry Andric 27481ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI 27581ad6265SDimitry Andricconstexpr void __compile_time_validate_integral(__arg_t __type) { 27681ad6265SDimitry Andric switch (__type) { 27781ad6265SDimitry Andric case __arg_t::__int: 27881ad6265SDimitry Andric case __arg_t::__long_long: 27981ad6265SDimitry Andric case __arg_t::__i128: 28081ad6265SDimitry Andric case __arg_t::__unsigned: 28181ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 28281ad6265SDimitry Andric case __arg_t::__u128: 28381ad6265SDimitry Andric return; 28481ad6265SDimitry Andric 28581ad6265SDimitry Andric default: 28681ad6265SDimitry Andric __throw_format_error("Argument isn't an integral type"); 28781ad6265SDimitry Andric } 28881ad6265SDimitry Andric} 28981ad6265SDimitry Andric 29081ad6265SDimitry Andric// _HasPrecision does the formatter have a precision? 29181ad6265SDimitry Andrictemplate <class _CharT, class _Tp, bool _HasPrecision = false> 29281ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void 29381ad6265SDimitry Andric__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, 29481ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx) { 29581ad6265SDimitry Andric formatter<_Tp, _CharT> __formatter; 29681ad6265SDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 29781ad6265SDimitry Andric // [format.string.std]/7 29881ad6265SDimitry Andric // ... If the corresponding formatting argument is not of integral type, or 29981ad6265SDimitry Andric // its value is negative for precision or non-positive for width, an 30081ad6265SDimitry Andric // exception of type format_error is thrown. 30181ad6265SDimitry Andric // 30281ad6265SDimitry Andric // Validate whether the arguments are integrals. 30381ad6265SDimitry Andric if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) { 30481ad6265SDimitry Andric // TODO FMT Remove this when parser v1 has been phased out. 30581ad6265SDimitry Andric if (__formatter.__width_needs_substitution()) 30681ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__width)); 30781ad6265SDimitry Andric 30881ad6265SDimitry Andric if constexpr (_HasPrecision) 30981ad6265SDimitry Andric if (__formatter.__precision_needs_substitution()) 31081ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision)); 31181ad6265SDimitry Andric } else { 31281ad6265SDimitry Andric if (__formatter.__parser_.__width_as_arg_) 31381ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); 31481ad6265SDimitry Andric 31581ad6265SDimitry Andric if constexpr (_HasPrecision) 31681ad6265SDimitry Andric if (__formatter.__parser_.__precision_as_arg_) 31781ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); 31881ad6265SDimitry Andric } 31981ad6265SDimitry Andric} 32081ad6265SDimitry Andric 32181ad6265SDimitry Andrictemplate <class _CharT> 32281ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx, 32381ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx, 32481ad6265SDimitry Andric __arg_t __type) { 32581ad6265SDimitry Andric switch (__type) { 32681ad6265SDimitry Andric case __arg_t::__none: 32781ad6265SDimitry Andric __throw_format_error("Invalid argument"); 32881ad6265SDimitry Andric case __arg_t::__boolean: 32981ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 33081ad6265SDimitry Andric case __arg_t::__char_type: 33181ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 33281ad6265SDimitry Andric case __arg_t::__int: 33381ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 33481ad6265SDimitry Andric case __arg_t::__long_long: 33581ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 33681ad6265SDimitry Andric case __arg_t::__i128: 33781ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 33881ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 33981ad6265SDimitry Andric# else 34081ad6265SDimitry Andric __throw_format_error("Invalid argument"); 34181ad6265SDimitry Andric# endif 34281ad6265SDimitry Andric return; 34381ad6265SDimitry Andric case __arg_t::__unsigned: 34481ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 34581ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 34681ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 34781ad6265SDimitry Andric case __arg_t::__u128: 34881ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 34981ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 35081ad6265SDimitry Andric# else 35181ad6265SDimitry Andric __throw_format_error("Invalid argument"); 35281ad6265SDimitry Andric# endif 35381ad6265SDimitry Andric return; 35481ad6265SDimitry Andric case __arg_t::__float: 35581ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 35681ad6265SDimitry Andric case __arg_t::__double: 35781ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 35881ad6265SDimitry Andric case __arg_t::__long_double: 35981ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 36081ad6265SDimitry Andric case __arg_t::__const_char_type_ptr: 36181ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 36281ad6265SDimitry Andric case __arg_t::__string_view: 36381ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 36481ad6265SDimitry Andric case __arg_t::__ptr: 36581ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 36681ad6265SDimitry Andric case __arg_t::__handle: 36781ad6265SDimitry Andric __throw_format_error("Handle should use __compile_time_validate_handle_argument"); 36881ad6265SDimitry Andric } 36981ad6265SDimitry Andric __throw_format_error("Invalid argument"); 37081ad6265SDimitry Andric} 37181ad6265SDimitry Andric 372349cc55cSDimitry Andrictemplate <class _CharT, class _ParseCtx, class _Ctx> 37381ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 374349cc55cSDimitry Andric__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 375349cc55cSDimitry Andric _ParseCtx& __parse_ctx, _Ctx& __ctx) { 376349cc55cSDimitry Andric __format::__parse_number_result __r = 377349cc55cSDimitry Andric __format::__parse_arg_id(__begin, __end, __parse_ctx); 378349cc55cSDimitry Andric 379*753f127fSDimitry Andric bool __parse = *__r.__ptr == _CharT(':'); 380349cc55cSDimitry Andric switch (*__r.__ptr) { 381349cc55cSDimitry Andric case _CharT(':'): 382349cc55cSDimitry Andric // The arg-id has a format-specifier, advance the input to the format-spec. 383349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr + 1); 384349cc55cSDimitry Andric break; 385349cc55cSDimitry Andric case _CharT('}'): 386349cc55cSDimitry Andric // The arg-id has no format-specifier. 387349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr); 388349cc55cSDimitry Andric break; 389349cc55cSDimitry Andric default: 390349cc55cSDimitry Andric __throw_format_error( 391349cc55cSDimitry Andric "The replacement field arg-id should terminate at a ':' or '}'"); 392349cc55cSDimitry Andric } 393349cc55cSDimitry Andric 39481ad6265SDimitry Andric if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 39581ad6265SDimitry Andric __arg_t __type = __ctx.arg(__r.__value); 39681ad6265SDimitry Andric if (__type == __arg_t::__handle) 39781ad6265SDimitry Andric __ctx.__handle(__r.__value).__parse(__parse_ctx); 39881ad6265SDimitry Andric else 39981ad6265SDimitry Andric __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 40081ad6265SDimitry Andric } else 401349cc55cSDimitry Andric _VSTD::visit_format_arg( 402349cc55cSDimitry Andric [&](auto __arg) { 403349cc55cSDimitry Andric if constexpr (same_as<decltype(__arg), monostate>) 404349cc55cSDimitry Andric __throw_format_error("Argument index out of bounds"); 40504eeddc0SDimitry Andric else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 40604eeddc0SDimitry Andric __arg.format(__parse_ctx, __ctx); 407349cc55cSDimitry Andric else { 408349cc55cSDimitry Andric formatter<decltype(__arg), _CharT> __formatter; 409*753f127fSDimitry Andric if (__parse) 410349cc55cSDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 411349cc55cSDimitry Andric __ctx.advance_to(__formatter.format(__arg, __ctx)); 412349cc55cSDimitry Andric } 413349cc55cSDimitry Andric }, 414349cc55cSDimitry Andric __ctx.arg(__r.__value)); 415349cc55cSDimitry Andric 416349cc55cSDimitry Andric __begin = __parse_ctx.begin(); 417349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 418349cc55cSDimitry Andric __throw_format_error("The replacement field misses a terminating '}'"); 419349cc55cSDimitry Andric 420349cc55cSDimitry Andric return ++__begin; 421349cc55cSDimitry Andric} 422349cc55cSDimitry Andric 423349cc55cSDimitry Andrictemplate <class _ParseCtx, class _Ctx> 42481ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator 425349cc55cSDimitry Andric__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 426349cc55cSDimitry Andric using _CharT = typename _ParseCtx::char_type; 427349cc55cSDimitry Andric static_assert(same_as<typename _Ctx::char_type, _CharT>); 428349cc55cSDimitry Andric 429349cc55cSDimitry Andric const _CharT* __begin = __parse_ctx.begin(); 430349cc55cSDimitry Andric const _CharT* __end = __parse_ctx.end(); 431349cc55cSDimitry Andric typename _Ctx::iterator __out_it = __ctx.out(); 432349cc55cSDimitry Andric while (__begin != __end) { 433349cc55cSDimitry Andric switch (*__begin) { 434349cc55cSDimitry Andric case _CharT('{'): 435349cc55cSDimitry Andric ++__begin; 436349cc55cSDimitry Andric if (__begin == __end) 437349cc55cSDimitry Andric __throw_format_error("The format string terminates at a '{'"); 438349cc55cSDimitry Andric 439349cc55cSDimitry Andric if (*__begin != _CharT('{')) [[likely]] { 440349cc55cSDimitry Andric __ctx.advance_to(_VSTD::move(__out_it)); 441349cc55cSDimitry Andric __begin = 442349cc55cSDimitry Andric __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 443349cc55cSDimitry Andric __out_it = __ctx.out(); 444349cc55cSDimitry Andric 445349cc55cSDimitry Andric // The output is written and __begin points to the next character. So 446349cc55cSDimitry Andric // start the next iteration. 447349cc55cSDimitry Andric continue; 448349cc55cSDimitry Andric } 449349cc55cSDimitry Andric // The string is an escape character. 450349cc55cSDimitry Andric break; 451349cc55cSDimitry Andric 452349cc55cSDimitry Andric case _CharT('}'): 453349cc55cSDimitry Andric ++__begin; 454349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 455349cc55cSDimitry Andric __throw_format_error( 456349cc55cSDimitry Andric "The format string contains an invalid escape sequence"); 457349cc55cSDimitry Andric 458349cc55cSDimitry Andric break; 459349cc55cSDimitry Andric } 460349cc55cSDimitry Andric 461349cc55cSDimitry Andric // Copy the character to the output verbatim. 462349cc55cSDimitry Andric *__out_it++ = *__begin++; 463349cc55cSDimitry Andric } 464349cc55cSDimitry Andric return __out_it; 465349cc55cSDimitry Andric} 466349cc55cSDimitry Andric 467349cc55cSDimitry Andric} // namespace __format 468349cc55cSDimitry Andric 46981ad6265SDimitry Andrictemplate <class _CharT, class... _Args> 47081ad6265SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __basic_format_string { 47181ad6265SDimitry Andric basic_string_view<_CharT> __str_; 47281ad6265SDimitry Andric 47381ad6265SDimitry Andric template <class _Tp> 47481ad6265SDimitry Andric requires convertible_to<const _Tp&, basic_string_view<_CharT>> 47581ad6265SDimitry Andric consteval __basic_format_string(const _Tp& __str) : __str_{__str} { 47681ad6265SDimitry Andric __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 47781ad6265SDimitry Andric _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 47881ad6265SDimitry Andric } 47981ad6265SDimitry Andric 48081ad6265SDimitry Andricprivate: 48181ad6265SDimitry Andric using _Context = __format::__compile_time_basic_format_context<_CharT>; 48281ad6265SDimitry Andric 48381ad6265SDimitry Andric static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 48481ad6265SDimitry Andric __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 48581ad6265SDimitry Andric 48681ad6265SDimitry Andric // TODO FMT remove this work-around when the AIX ICE has been resolved. 48781ad6265SDimitry Andric# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 48881ad6265SDimitry Andric template <class _Tp> 48981ad6265SDimitry Andric static constexpr __format::__compile_time_handle<_CharT> __get_handle() { 49081ad6265SDimitry Andric __format::__compile_time_handle<_CharT> __handle; 49181ad6265SDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 49281ad6265SDimitry Andric __handle.template __enable<_Tp>(); 49381ad6265SDimitry Andric 49481ad6265SDimitry Andric return __handle; 49581ad6265SDimitry Andric } 49681ad6265SDimitry Andric 49781ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ 49881ad6265SDimitry Andric __get_handle<_Args>()...}; 49981ad6265SDimitry Andric# else 50081ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 50181ad6265SDimitry Andric using _Tp = remove_cvref_t<_Args>; 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# endif 50981ad6265SDimitry Andric}; 51081ad6265SDimitry Andric 51181ad6265SDimitry Andrictemplate <class... _Args> 51281ad6265SDimitry Andricusing __format_string_t = __basic_format_string<char, type_identity_t<_Args>...>; 51381ad6265SDimitry Andric 51481ad6265SDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 51581ad6265SDimitry Andrictemplate <class... _Args> 51681ad6265SDimitry Andricusing __wformat_string_t = __basic_format_string<wchar_t, type_identity_t<_Args>...>; 51781ad6265SDimitry Andric#endif 51881ad6265SDimitry Andric 5194824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 520349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 5214824e7fdSDimitry Andric __vformat_to( 5224824e7fdSDimitry Andric _OutIt __out_it, basic_string_view<_CharT> __fmt, 5234824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 5244824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 5254824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 526349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 527349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 5284824e7fdSDimitry Andric else { 52981ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 5304824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 5314824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 53281ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 53381ad6265SDimitry Andric __args)); 53481ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 5354824e7fdSDimitry Andric } 536349cc55cSDimitry Andric} 537349cc55cSDimitry Andric 53881ad6265SDimitry Andric// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 53981ad6265SDimitry Andric// https://reviews.llvm.org/D110499#inline-1180704 54081ad6265SDimitry Andric// TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 541349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 5424824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5434824e7fdSDimitry Andricvformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 544349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 545349cc55cSDimitry Andric} 546349cc55cSDimitry Andric 547349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 548349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 5494824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5504824e7fdSDimitry Andricvformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 551349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 552349cc55cSDimitry Andric} 553349cc55cSDimitry Andric#endif 554349cc55cSDimitry Andric 555349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 5564824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 557*753f127fSDimitry Andricformat_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, _Args&&... __args) { 55881ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, 5594824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 560349cc55cSDimitry Andric} 561349cc55cSDimitry Andric 562349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 563349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 5644824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 565*753f127fSDimitry Andricformat_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 56681ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, 5674824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 568349cc55cSDimitry Andric} 569349cc55cSDimitry Andric#endif 570349cc55cSDimitry Andric 5714824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 572349cc55cSDimitry Andricvformat(string_view __fmt, format_args __args) { 573349cc55cSDimitry Andric string __res; 574349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 575349cc55cSDimitry Andric return __res; 576349cc55cSDimitry Andric} 577349cc55cSDimitry Andric 578349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 5794824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 580349cc55cSDimitry Andricvformat(wstring_view __fmt, wformat_args __args) { 581349cc55cSDimitry Andric wstring __res; 582349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 583349cc55cSDimitry Andric return __res; 584349cc55cSDimitry Andric} 585349cc55cSDimitry Andric#endif 586349cc55cSDimitry Andric 587349cc55cSDimitry Andrictemplate <class... _Args> 58881ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt, 589*753f127fSDimitry Andric _Args&&... __args) { 59081ad6265SDimitry Andric return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...)); 591349cc55cSDimitry Andric} 592349cc55cSDimitry Andric 593349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 594349cc55cSDimitry Andrictemplate <class... _Args> 5954824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 596*753f127fSDimitry Andricformat(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { 59781ad6265SDimitry Andric return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...)); 598349cc55cSDimitry Andric} 599349cc55cSDimitry Andric#endif 600349cc55cSDimitry Andric 60181ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 60281ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 60381ad6265SDimitry Andric basic_string_view<_CharT> __fmt, 60481ad6265SDimitry Andric basic_format_args<_Context> __args) { 60581ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 60681ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 60781ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 60881ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 60981ad6265SDimitry Andric} 61081ad6265SDimitry Andric 611349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 61281ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 613*753f127fSDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, _Args&&... __args) { 61481ad6265SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...)); 615349cc55cSDimitry Andric} 616349cc55cSDimitry Andric 617349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 618349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 619349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 62081ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt, 621*753f127fSDimitry Andric _Args&&... __args) { 62281ad6265SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...)); 623349cc55cSDimitry Andric} 624349cc55cSDimitry Andric#endif 625349cc55cSDimitry Andric 62681ad6265SDimitry Andrictemplate <class _CharT> 62781ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 62881ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 62981ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 63081ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 63181ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 63281ad6265SDimitry Andric} 63381ad6265SDimitry Andric 634349cc55cSDimitry Andrictemplate <class... _Args> 63581ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 636*753f127fSDimitry Andricformatted_size(__format_string_t<_Args...> __fmt, _Args&&... __args) { 63781ad6265SDimitry Andric return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); 638349cc55cSDimitry Andric} 639349cc55cSDimitry Andric 640349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 641349cc55cSDimitry Andrictemplate <class... _Args> 64281ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 643*753f127fSDimitry Andricformatted_size(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { 64481ad6265SDimitry Andric return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); 645349cc55cSDimitry Andric} 646349cc55cSDimitry Andric#endif 647349cc55cSDimitry Andric 648349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION 649349cc55cSDimitry Andric 6504824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 651349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 6524824e7fdSDimitry Andric __vformat_to( 6534824e7fdSDimitry Andric _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 6544824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 6554824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 6564824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 657349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 658349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 659349cc55cSDimitry Andric _VSTD::move(__loc))); 6604824e7fdSDimitry Andric else { 66181ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 6624824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 6634824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 66481ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 66581ad6265SDimitry Andric __args, _VSTD::move(__loc))); 66681ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 6674824e7fdSDimitry Andric } 668349cc55cSDimitry Andric} 669349cc55cSDimitry Andric 670349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 6714824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6724824e7fdSDimitry Andric _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 673349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 674349cc55cSDimitry Andric __args); 675349cc55cSDimitry Andric} 676349cc55cSDimitry Andric 677349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 678349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 6794824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6804824e7fdSDimitry Andric _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 681349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 682349cc55cSDimitry Andric __args); 683349cc55cSDimitry Andric} 684349cc55cSDimitry Andric#endif 685349cc55cSDimitry Andric 686349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 68781ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 688*753f127fSDimitry Andricformat_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { 68981ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, 6904824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 691349cc55cSDimitry Andric} 692349cc55cSDimitry Andric 693349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 694349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 69581ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 696*753f127fSDimitry Andricformat_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 69781ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, 6984824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 699349cc55cSDimitry Andric} 700349cc55cSDimitry Andric#endif 701349cc55cSDimitry Andric 7024824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 703349cc55cSDimitry Andricvformat(locale __loc, string_view __fmt, format_args __args) { 704349cc55cSDimitry Andric string __res; 705349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 706349cc55cSDimitry Andric __args); 707349cc55cSDimitry Andric return __res; 708349cc55cSDimitry Andric} 709349cc55cSDimitry Andric 710349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 7114824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 712349cc55cSDimitry Andricvformat(locale __loc, wstring_view __fmt, wformat_args __args) { 713349cc55cSDimitry Andric wstring __res; 714349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 715349cc55cSDimitry Andric __args); 716349cc55cSDimitry Andric return __res; 717349cc55cSDimitry Andric} 718349cc55cSDimitry Andric#endif 719349cc55cSDimitry Andric 720349cc55cSDimitry Andrictemplate <class... _Args> 72181ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, 72281ad6265SDimitry Andric __format_string_t<_Args...> __fmt, 723*753f127fSDimitry Andric _Args&&... __args) { 72481ad6265SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, 725349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 726349cc55cSDimitry Andric} 727349cc55cSDimitry Andric 728349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 729349cc55cSDimitry Andrictemplate <class... _Args> 7304824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 731*753f127fSDimitry Andricformat(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 73281ad6265SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, 733349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 734349cc55cSDimitry Andric} 735349cc55cSDimitry Andric#endif 736349cc55cSDimitry Andric 73781ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 73881ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 73981ad6265SDimitry Andric locale __loc, basic_string_view<_CharT> __fmt, 74081ad6265SDimitry Andric basic_format_args<_Context> __args) { 74181ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 74281ad6265SDimitry Andric _VSTD::__format::__vformat_to( 74381ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 74481ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 74581ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 74681ad6265SDimitry Andric} 74781ad6265SDimitry Andric 748349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 74981ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 75081ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt, 751*753f127fSDimitry Andric _Args&&... __args) { 75281ad6265SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, 753349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 754349cc55cSDimitry Andric} 755349cc55cSDimitry Andric 756349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 757349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 75881ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 75981ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt, 760*753f127fSDimitry Andric _Args&&... __args) { 76181ad6265SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, 762349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 763349cc55cSDimitry Andric} 764349cc55cSDimitry Andric#endif 765349cc55cSDimitry Andric 76681ad6265SDimitry Andrictemplate <class _CharT> 76781ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 76881ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 76981ad6265SDimitry Andric _VSTD::__format::__vformat_to( 77081ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 77181ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 77281ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 77381ad6265SDimitry Andric} 77481ad6265SDimitry Andric 775349cc55cSDimitry Andrictemplate <class... _Args> 77681ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 777*753f127fSDimitry Andricformatted_size(locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { 77881ad6265SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); 779349cc55cSDimitry Andric} 780349cc55cSDimitry Andric 781349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 782349cc55cSDimitry Andrictemplate <class... _Args> 78381ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 784*753f127fSDimitry Andricformatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { 78581ad6265SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); 786349cc55cSDimitry Andric} 787349cc55cSDimitry Andric#endif 788349cc55cSDimitry Andric 789349cc55cSDimitry Andric#endif // _LIBCPP_HAS_NO_LOCALIZATION 790349cc55cSDimitry Andric 791fe6060f1SDimitry Andric#endif //_LIBCPP_STD_VER > 17 792fe6060f1SDimitry Andric 793fe6060f1SDimitry Andric_LIBCPP_END_NAMESPACE_STD 794fe6060f1SDimitry Andric 7956e75b2fbSDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 7966e75b2fbSDimitry Andric 797fe6060f1SDimitry Andric#endif // _LIBCPP_FORMAT 798