1081c1db0SMark de Wever// -*- C++ -*- 2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===// 3081c1db0SMark de Wever// 4081c1db0SMark de Wever// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5081c1db0SMark de Wever// See https://llvm.org/LICENSE.txt for license information. 6081c1db0SMark de Wever// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7081c1db0SMark de Wever// 8081c1db0SMark de Wever//===----------------------------------------------------------------------===// 9081c1db0SMark de Wever 10081c1db0SMark de Wever#ifndef _LIBCPP_FORMAT 11081c1db0SMark de Wever#define _LIBCPP_FORMAT 12081c1db0SMark de Wever 13081c1db0SMark de Wever/* 14081c1db0SMark de Wever 15081c1db0SMark de Wevernamespace std { 160922ce56SMark de Wever // [format.context], class template basic_format_context 174684857aSMark de Wever template<class Out, class charT> class basic_format_context; 180922ce56SMark de Wever using format_context = basic_format_context<unspecified, char>; 190922ce56SMark de Wever using wformat_context = basic_format_context<unspecified, wchar_t>; 200922ce56SMark de Wever 210922ce56SMark de Wever // [format.args], class template basic_format_args 224684857aSMark de Wever template<class Context> class basic_format_args; 230922ce56SMark de Wever using format_args = basic_format_args<format_context>; 240922ce56SMark de Wever using wformat_args = basic_format_args<wformat_context>; 250922ce56SMark de Wever 26*13249036SMark de Wever // [format.fmt.string], class template basic_format_string 27aed5ddf8SMark de Wever template<class charT, class... Args> 28*13249036SMark de Wever struct basic_format_string { // since C++23, exposition only before C++23 29*13249036SMark de Wever private: 30*13249036SMark de Wever basic_string_view<charT> str; // exposition only 31aed5ddf8SMark de Wever 32*13249036SMark de Wever public: 33*13249036SMark de Wever template<class T> consteval basic_format_string(const T& s); 34*13249036SMark de Wever 35*13249036SMark de Wever constexpr basic_string_view<charT> get() const noexcept { return str; } 36*13249036SMark de Wever }; 37aed5ddf8SMark de Wever template<class... Args> 38*13249036SMark de Wever using format_string = // since C++23, exposition only before C++23 39*13249036SMark de Wever basic_format_string<char, type_identity_t<Args>...>; 40aed5ddf8SMark de Wever template<class... Args> 41*13249036SMark de Wever using wformat_string = // since C++23, exposition only before C++23 42*13249036SMark de Wever basic_format_string<wchar_t, type_identity_t<Args>...>; 43aed5ddf8SMark de Wever 44d7444d9fSMark de Wever // [format.functions], formatting functions 45d7444d9fSMark de Wever template<class... Args> 46606e2808SMark de Wever string format(format-string<Args...> fmt, Args&&... args); 47d7444d9fSMark de Wever template<class... Args> 48606e2808SMark de Wever wstring format(wformat-string<Args...> fmt, Args&&... args); 49d7444d9fSMark de Wever template<class... Args> 50606e2808SMark de Wever string format(const locale& loc, format-string<Args...> fmt, Args&&... args); 51d7444d9fSMark de Wever template<class... Args> 52606e2808SMark de Wever wstring format(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 53d7444d9fSMark de Wever 54d7444d9fSMark de Wever string vformat(string_view fmt, format_args args); 55d7444d9fSMark de Wever wstring vformat(wstring_view fmt, wformat_args args); 56d7444d9fSMark de Wever string vformat(const locale& loc, string_view fmt, format_args args); 57d7444d9fSMark de Wever wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); 58d7444d9fSMark de Wever 59d7444d9fSMark de Wever template<class Out, class... Args> 60606e2808SMark de Wever Out format_to(Out out, format-string<Args...> fmt, Args&&... args); 61d7444d9fSMark de Wever template<class Out, class... Args> 62606e2808SMark de Wever Out format_to(Out out, wformat-string<Args...> fmt, Args&&... args); 63d7444d9fSMark de Wever template<class Out, class... Args> 64606e2808SMark de Wever Out format_to(Out out, const locale& loc, format-string<Args...> fmt, Args&&... args); 65d7444d9fSMark de Wever template<class Out, class... Args> 66606e2808SMark de Wever Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, Args&&... args); 67d7444d9fSMark de Wever 68d7444d9fSMark de Wever template<class Out> 690e9979afSMark de Wever Out vformat_to(Out out, string_view fmt, format_args args); 70d7444d9fSMark de Wever template<class Out> 710e9979afSMark de Wever Out vformat_to(Out out, wstring_view fmt, wformat_args args); 72d7444d9fSMark de Wever template<class Out> 73d7444d9fSMark de Wever Out vformat_to(Out out, const locale& loc, string_view fmt, 740e9979afSMark de Wever format_args char> args); 75d7444d9fSMark de Wever template<class Out> 76d7444d9fSMark de Wever Out vformat_to(Out out, const locale& loc, wstring_view fmt, 770e9979afSMark de Wever wformat_args args); 78d7444d9fSMark de Wever 79d7444d9fSMark de Wever template<class Out> struct format_to_n_result { 80d7444d9fSMark de Wever Out out; 81d7444d9fSMark de Wever iter_difference_t<Out> size; 82d7444d9fSMark de Wever }; 83d7444d9fSMark de Wever template<class Out, class... Args> 84d7444d9fSMark de Wever format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 85606e2808SMark de Wever format-string<Args...> fmt, Args&&... args); 86d7444d9fSMark de Wever template<class Out, class... Args> 87d7444d9fSMark de Wever format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 88606e2808SMark de Wever wformat-string<Args...> fmt, Args&&... args); 89d7444d9fSMark de Wever template<class Out, class... Args> 90d7444d9fSMark de Wever format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 91aed5ddf8SMark de Wever const locale& loc, format-string<Args...> fmt, 92606e2808SMark de Wever Args&&... args); 93d7444d9fSMark de Wever template<class Out, class... Args> 94d7444d9fSMark de Wever format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, 95aed5ddf8SMark de Wever const locale& loc, wformat-string<Args...> fmt, 96606e2808SMark de Wever Args&&... args); 97d7444d9fSMark de Wever 98d7444d9fSMark de Wever template<class... Args> 99606e2808SMark de Wever size_t formatted_size(format-string<Args...> fmt, Args&&... args); 100d7444d9fSMark de Wever template<class... Args> 101606e2808SMark de Wever size_t formatted_size(wformat-string<Args...> fmt, Args&&... args); 102d7444d9fSMark de Wever template<class... Args> 103606e2808SMark de Wever size_t formatted_size(const locale& loc, format-string<Args...> fmt, Args&&... args); 104d7444d9fSMark de Wever template<class... Args> 105606e2808SMark de Wever size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, Args&&... args); 106d7444d9fSMark de Wever 107d7444d9fSMark de Wever // [format.formatter], formatter 1084684857aSMark de Wever template<class T, class charT = char> struct formatter; 109d7444d9fSMark de Wever 1100922ce56SMark de Wever // [format.parse.ctx], class template basic_format_parse_context 1114684857aSMark de Wever template<class charT> class basic_format_parse_context; 1120922ce56SMark de Wever using format_parse_context = basic_format_parse_context<char>; 1130922ce56SMark de Wever using wformat_parse_context = basic_format_parse_context<wchar_t>; 1140922ce56SMark de Wever 1150922ce56SMark de Wever // [format.arguments], arguments 1160922ce56SMark de Wever // [format.arg], class template basic_format_arg 1174684857aSMark de Wever template<class Context> class basic_format_arg; 1180922ce56SMark de Wever 1190922ce56SMark de Wever template<class Visitor, class Context> 1200922ce56SMark de Wever see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); 1210922ce56SMark de Wever 1220922ce56SMark de Wever // [format.arg.store], class template format-arg-store 1234684857aSMark de Wever template<class Context, class... Args> struct format-arg-store; // exposition only 1240922ce56SMark de Wever 1250922ce56SMark de Wever template<class Context = format_context, class... Args> 1260922ce56SMark de Wever format-arg-store<Context, Args...> 127606e2808SMark de Wever make_format_args(Args&&... args); 1280922ce56SMark de Wever template<class... Args> 1290922ce56SMark de Wever format-arg-store<wformat_context, Args...> 130606e2808SMark de Wever make_wformat_args(Args&&... args); 1310922ce56SMark de Wever 132081c1db0SMark de Wever // [format.error], class format_error 1334684857aSMark de Wever class format_error; 134081c1db0SMark de Wever} 135081c1db0SMark de Wever 136081c1db0SMark de Wever*/ 137081c1db0SMark de Wever 138385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler 139d2bc4fa3SMark de Wever// Make sure all feature-test macros are available. 140d618a1ccSMark de Wever#include <version> 1418711fcaeSLouis Dionne// Enable the contents of the header only when libc++ was built with experimental features enabled. 142d618a1ccSMark de Wever#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 143d618a1ccSMark de Wever 1442e2f3158SNikolas Klauser#include <__algorithm/clamp.h> 145081c1db0SMark de Wever#include <__config> 146d7444d9fSMark de Wever#include <__debug> 147555214cbSMark de Wever#include <__format/buffer.h> 14815c809e8SMark de Wever#include <__format/concepts.h> 14988930229SMark de Wever#include <__format/enable_insertable.h> 1500922ce56SMark de Wever#include <__format/format_arg.h> 1514d8268fbSMark de Wever#include <__format/format_arg_store.h> 1520922ce56SMark de Wever#include <__format/format_args.h> 1530922ce56SMark de Wever#include <__format/format_context.h> 15416342e39SMark de Wever#include <__format/format_error.h> 1553e9689d7SMark de Wever#include <__format/format_fwd.h> 156de9df3f5SMark de Wever#include <__format/format_parse_context.h> 157d7444d9fSMark de Wever#include <__format/format_string.h> 1585baa4ee3SMark de Wever#include <__format/format_to_n_result.h> 159d7444d9fSMark de Wever#include <__format/formatter.h> 1607fb9f99fSMark de Wever#include <__format/formatter_bool.h> 16149e736d8SMark de Wever#include <__format/formatter_char.h> 162db2944e3SMark de Wever#include <__format/formatter_floating_point.h> 1633e9689d7SMark de Wever#include <__format/formatter_integer.h> 164787ccd34SMark de Wever#include <__format/formatter_pointer.h> 165d550930aSMark de Wever#include <__format/formatter_string.h> 166d550930aSMark de Wever#include <__format/parser_std_format_spec.h> 167857a78c0SMark de Wever#include <__format/unicode.h> 1684cd04d16SMark de Wever#include <__iterator/back_insert_iterator.h> 1693cd4531bSNikolas Klauser#include <__iterator/incrementable_traits.h> 170d7444d9fSMark de Wever#include <__variant/monostate.h> 1710922ce56SMark de Wever#include <array> 172d7444d9fSMark de Wever#include <concepts> 173d7444d9fSMark de Wever#include <string> 174d7444d9fSMark de Wever#include <string_view> 175d7444d9fSMark de Wever#include <type_traits> 176d7444d9fSMark de Wever 177d7444d9fSMark de Wever#ifndef _LIBCPP_HAS_NO_LOCALIZATION 178d7444d9fSMark de Wever#include <locale> 179d7444d9fSMark de Wever#endif 18071909de3SMark de Wever 181081c1db0SMark de Wever#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 182081c1db0SMark de Wever# pragma GCC system_header 183081c1db0SMark de Wever#endif 184081c1db0SMark de Wever 1850922ce56SMark de Wever_LIBCPP_BEGIN_NAMESPACE_STD 1860922ce56SMark de Wever 1870922ce56SMark de Wever#if _LIBCPP_STD_VER > 17 1880922ce56SMark de Wever 189f0bb6c76SMark de Wever// TODO FMT Move the implementation in this file to its own granular headers. 190f0bb6c76SMark de Wever 1910922ce56SMark de Wever// TODO FMT Evaluate which templates should be external templates. This 1920922ce56SMark de Wever// improves the efficiency of the header. However since the header is still 1930922ce56SMark de Wever// under heavy development and not all classes are stable it makes no sense 1940922ce56SMark de Wever// to do this optimization now. 1950922ce56SMark de Wever 1960922ce56SMark de Weverusing format_args = basic_format_args<format_context>; 197f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1980922ce56SMark de Weverusing wformat_args = basic_format_args<wformat_context>; 199f4c1258dSLouis Dionne#endif 2000922ce56SMark de Wever 2014d8268fbSMark de Wevertemplate <class _Context = format_context, class... _Args> 202606e2808SMark de Wever_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { 203606e2808SMark de Wever return _VSTD::__format_arg_store<_Context, _Args...>(__args...); 2040922ce56SMark de Wever} 2050922ce56SMark de Wever 206f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2070922ce56SMark de Wevertemplate <class... _Args> 208606e2808SMark de Wever_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) { 209606e2808SMark de Wever return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...); 2100922ce56SMark de Wever} 211f4c1258dSLouis Dionne#endif 212f4c1258dSLouis Dionne 213d7444d9fSMark de Wevernamespace __format { 214d7444d9fSMark de Wever 215aed5ddf8SMark de Wever/// Helper class parse and handle argument. 216aed5ddf8SMark de Wever/// 217aed5ddf8SMark de Wever/// When parsing a handle which is not enabled the code is ill-formed. 218aed5ddf8SMark de Wever/// This helper uses the parser of the appropriate formatter for the stored type. 219aed5ddf8SMark de Wevertemplate <class _CharT> 220aed5ddf8SMark de Weverclass _LIBCPP_TEMPLATE_VIS __compile_time_handle { 221aed5ddf8SMark de Weverpublic: 222aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI 223aed5ddf8SMark de Wever constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } 224aed5ddf8SMark de Wever 225aed5ddf8SMark de Wever template <class _Tp> 226aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 227aed5ddf8SMark de Wever __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { 228aed5ddf8SMark de Wever formatter<_Tp, _CharT> __f; 229aed5ddf8SMark de Wever __parse_ctx.advance_to(__f.parse(__parse_ctx)); 230aed5ddf8SMark de Wever }; 231aed5ddf8SMark de Wever } 232aed5ddf8SMark de Wever 233aed5ddf8SMark de Wever // Before calling __parse the proper handler needs to be set with __enable. 234aed5ddf8SMark de Wever // The default handler isn't a core constant expression. 235aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 236aed5ddf8SMark de Wever : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {} 237aed5ddf8SMark de Wever 238aed5ddf8SMark de Weverprivate: 239aed5ddf8SMark de Wever void (*__parse_)(basic_format_parse_context<_CharT>&); 240aed5ddf8SMark de Wever}; 241aed5ddf8SMark de Wever 242aed5ddf8SMark de Wever// Dummy format_context only providing the parts used during constant 243*13249036SMark de Wever// validation of the basic_format_string. 244aed5ddf8SMark de Wevertemplate <class _CharT> 245aed5ddf8SMark de Weverstruct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 246aed5ddf8SMark de Weverpublic: 247aed5ddf8SMark de Wever using char_type = _CharT; 248aed5ddf8SMark de Wever 249aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 250aed5ddf8SMark de Wever const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 251aed5ddf8SMark de Wever : __args_(__args), __handles_(__handles), __size_(__size) {} 252aed5ddf8SMark de Wever 253aed5ddf8SMark de Wever // During the compile-time validation nothing needs to be written. 254aed5ddf8SMark de Wever // Therefore all operations of this iterator are a NOP. 255aed5ddf8SMark de Wever struct iterator { 256aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 257aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 258aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 259aed5ddf8SMark de Wever }; 260aed5ddf8SMark de Wever 261aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 262aed5ddf8SMark de Wever if (__id >= __size_) 263aed5ddf8SMark de Wever __throw_format_error("Argument index out of bounds"); 264aed5ddf8SMark de Wever return __args_[__id]; 265aed5ddf8SMark de Wever } 266aed5ddf8SMark de Wever 267aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 268aed5ddf8SMark de Wever if (__id >= __size_) 269aed5ddf8SMark de Wever __throw_format_error("Argument index out of bounds"); 270aed5ddf8SMark de Wever return __handles_[__id]; 271aed5ddf8SMark de Wever } 272aed5ddf8SMark de Wever 273aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 274aed5ddf8SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 275aed5ddf8SMark de Wever 276aed5ddf8SMark de Weverprivate: 277aed5ddf8SMark de Wever const __arg_t* __args_; 278aed5ddf8SMark de Wever const __compile_time_handle<_CharT>* __handles_; 279aed5ddf8SMark de Wever size_t __size_; 280aed5ddf8SMark de Wever}; 281aed5ddf8SMark de Wever 282aed5ddf8SMark de Wever_LIBCPP_HIDE_FROM_ABI 283aed5ddf8SMark de Weverconstexpr void __compile_time_validate_integral(__arg_t __type) { 284aed5ddf8SMark de Wever switch (__type) { 285aed5ddf8SMark de Wever case __arg_t::__int: 286aed5ddf8SMark de Wever case __arg_t::__long_long: 287aed5ddf8SMark de Wever case __arg_t::__i128: 288aed5ddf8SMark de Wever case __arg_t::__unsigned: 289aed5ddf8SMark de Wever case __arg_t::__unsigned_long_long: 290aed5ddf8SMark de Wever case __arg_t::__u128: 291aed5ddf8SMark de Wever return; 292aed5ddf8SMark de Wever 293aed5ddf8SMark de Wever default: 294aed5ddf8SMark de Wever __throw_format_error("Argument isn't an integral type"); 295aed5ddf8SMark de Wever } 296aed5ddf8SMark de Wever} 297aed5ddf8SMark de Wever 298aed5ddf8SMark de Wever// _HasPrecision does the formatter have a precision? 299aed5ddf8SMark de Wevertemplate <class _CharT, class _Tp, bool _HasPrecision = false> 300aed5ddf8SMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr void 301aed5ddf8SMark de Wever__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, 302aed5ddf8SMark de Wever __compile_time_basic_format_context<_CharT>& __ctx) { 303aed5ddf8SMark de Wever formatter<_Tp, _CharT> __formatter; 304aed5ddf8SMark de Wever __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 305aed5ddf8SMark de Wever // [format.string.std]/7 306aed5ddf8SMark de Wever // ... If the corresponding formatting argument is not of integral type, or 307aed5ddf8SMark de Wever // its value is negative for precision or non-positive for width, an 308aed5ddf8SMark de Wever // exception of type format_error is thrown. 309aed5ddf8SMark de Wever // 310aed5ddf8SMark de Wever // Validate whether the arguments are integrals. 31177ad77c0SMark de Wever if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) { 31277ad77c0SMark de Wever // TODO FMT Remove this when parser v1 has been phased out. 313aed5ddf8SMark de Wever if (__formatter.__width_needs_substitution()) 314aed5ddf8SMark de Wever __format::__compile_time_validate_integral(__ctx.arg(__formatter.__width)); 315aed5ddf8SMark de Wever 316aed5ddf8SMark de Wever if constexpr (_HasPrecision) 317aed5ddf8SMark de Wever if (__formatter.__precision_needs_substitution()) 318aed5ddf8SMark de Wever __format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision)); 31977ad77c0SMark de Wever } else { 32077ad77c0SMark de Wever if (__formatter.__parser_.__width_as_arg_) 32177ad77c0SMark de Wever __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); 32277ad77c0SMark de Wever 32377ad77c0SMark de Wever if constexpr (_HasPrecision) 32477ad77c0SMark de Wever if (__formatter.__parser_.__precision_as_arg_) 32577ad77c0SMark de Wever __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); 32677ad77c0SMark de Wever } 327aed5ddf8SMark de Wever} 328aed5ddf8SMark de Wever 329aed5ddf8SMark de Wevertemplate <class _CharT> 330aed5ddf8SMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx, 331aed5ddf8SMark de Wever __compile_time_basic_format_context<_CharT>& __ctx, 332aed5ddf8SMark de Wever __arg_t __type) { 333aed5ddf8SMark de Wever switch (__type) { 334aed5ddf8SMark de Wever case __arg_t::__none: 335aed5ddf8SMark de Wever __throw_format_error("Invalid argument"); 336aed5ddf8SMark de Wever case __arg_t::__boolean: 337aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 338aed5ddf8SMark de Wever case __arg_t::__char_type: 339aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 340aed5ddf8SMark de Wever case __arg_t::__int: 341aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 342aed5ddf8SMark de Wever case __arg_t::__long_long: 343aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 344aed5ddf8SMark de Wever case __arg_t::__i128: 345aed5ddf8SMark de Wever# ifndef _LIBCPP_HAS_NO_INT128 346aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 347aed5ddf8SMark de Wever# else 348aed5ddf8SMark de Wever __throw_format_error("Invalid argument"); 349aed5ddf8SMark de Wever# endif 350aed5ddf8SMark de Wever return; 351aed5ddf8SMark de Wever case __arg_t::__unsigned: 352aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 353aed5ddf8SMark de Wever case __arg_t::__unsigned_long_long: 354aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 355aed5ddf8SMark de Wever case __arg_t::__u128: 356aed5ddf8SMark de Wever# ifndef _LIBCPP_HAS_NO_INT128 357aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 358aed5ddf8SMark de Wever# else 359aed5ddf8SMark de Wever __throw_format_error("Invalid argument"); 360aed5ddf8SMark de Wever# endif 361aed5ddf8SMark de Wever return; 362aed5ddf8SMark de Wever case __arg_t::__float: 363aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 364aed5ddf8SMark de Wever case __arg_t::__double: 365aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 366aed5ddf8SMark de Wever case __arg_t::__long_double: 367aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 368aed5ddf8SMark de Wever case __arg_t::__const_char_type_ptr: 369aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 370aed5ddf8SMark de Wever case __arg_t::__string_view: 371aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 372aed5ddf8SMark de Wever case __arg_t::__ptr: 373aed5ddf8SMark de Wever return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 374aed5ddf8SMark de Wever case __arg_t::__handle: 375aed5ddf8SMark de Wever __throw_format_error("Handle should use __compile_time_validate_handle_argument"); 376aed5ddf8SMark de Wever } 377aed5ddf8SMark de Wever __throw_format_error("Invalid argument"); 378aed5ddf8SMark de Wever} 379aed5ddf8SMark de Wever 380d7444d9fSMark de Wevertemplate <class _CharT, class _ParseCtx, class _Ctx> 381aed5ddf8SMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 382d7444d9fSMark de Wever__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 383d7444d9fSMark de Wever _ParseCtx& __parse_ctx, _Ctx& __ctx) { 384d7444d9fSMark de Wever __format::__parse_number_result __r = 385d7444d9fSMark de Wever __format::__parse_arg_id(__begin, __end, __parse_ctx); 386d7444d9fSMark de Wever 38765897292SMark de Wever bool __parse = *__r.__ptr == _CharT(':'); 388d7444d9fSMark de Wever switch (*__r.__ptr) { 389d7444d9fSMark de Wever case _CharT(':'): 390d7444d9fSMark de Wever // The arg-id has a format-specifier, advance the input to the format-spec. 391d7444d9fSMark de Wever __parse_ctx.advance_to(__r.__ptr + 1); 392d7444d9fSMark de Wever break; 393d7444d9fSMark de Wever case _CharT('}'): 394d7444d9fSMark de Wever // The arg-id has no format-specifier. 395d7444d9fSMark de Wever __parse_ctx.advance_to(__r.__ptr); 396d7444d9fSMark de Wever break; 397d7444d9fSMark de Wever default: 398d7444d9fSMark de Wever __throw_format_error( 399d7444d9fSMark de Wever "The replacement field arg-id should terminate at a ':' or '}'"); 400d7444d9fSMark de Wever } 401d7444d9fSMark de Wever 402aed5ddf8SMark de Wever if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 403aed5ddf8SMark de Wever __arg_t __type = __ctx.arg(__r.__value); 404aed5ddf8SMark de Wever if (__type == __arg_t::__handle) 405aed5ddf8SMark de Wever __ctx.__handle(__r.__value).__parse(__parse_ctx); 406aed5ddf8SMark de Wever else 407aed5ddf8SMark de Wever __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 408aed5ddf8SMark de Wever } else 409d7444d9fSMark de Wever _VSTD::visit_format_arg( 410d7444d9fSMark de Wever [&](auto __arg) { 411d7444d9fSMark de Wever if constexpr (same_as<decltype(__arg), monostate>) 412d7444d9fSMark de Wever __throw_format_error("Argument index out of bounds"); 413ade6d0d8SMark de Wever else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 414ade6d0d8SMark de Wever __arg.format(__parse_ctx, __ctx); 415d7444d9fSMark de Wever else { 416d7444d9fSMark de Wever formatter<decltype(__arg), _CharT> __formatter; 41765897292SMark de Wever if (__parse) 418d7444d9fSMark de Wever __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 419d7444d9fSMark de Wever __ctx.advance_to(__formatter.format(__arg, __ctx)); 420d7444d9fSMark de Wever } 421d7444d9fSMark de Wever }, 422d7444d9fSMark de Wever __ctx.arg(__r.__value)); 423d7444d9fSMark de Wever 424d7444d9fSMark de Wever __begin = __parse_ctx.begin(); 425d7444d9fSMark de Wever if (__begin == __end || *__begin != _CharT('}')) 426d7444d9fSMark de Wever __throw_format_error("The replacement field misses a terminating '}'"); 427d7444d9fSMark de Wever 428d7444d9fSMark de Wever return ++__begin; 429d7444d9fSMark de Wever} 430d7444d9fSMark de Wever 431d7444d9fSMark de Wevertemplate <class _ParseCtx, class _Ctx> 432aed5ddf8SMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator 433d7444d9fSMark de Wever__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 434d7444d9fSMark de Wever using _CharT = typename _ParseCtx::char_type; 435d7444d9fSMark de Wever static_assert(same_as<typename _Ctx::char_type, _CharT>); 436d7444d9fSMark de Wever 437d7444d9fSMark de Wever const _CharT* __begin = __parse_ctx.begin(); 438d7444d9fSMark de Wever const _CharT* __end = __parse_ctx.end(); 439d7444d9fSMark de Wever typename _Ctx::iterator __out_it = __ctx.out(); 440d7444d9fSMark de Wever while (__begin != __end) { 441d7444d9fSMark de Wever switch (*__begin) { 442d7444d9fSMark de Wever case _CharT('{'): 443d7444d9fSMark de Wever ++__begin; 444d7444d9fSMark de Wever if (__begin == __end) 445d7444d9fSMark de Wever __throw_format_error("The format string terminates at a '{'"); 446d7444d9fSMark de Wever 447d7444d9fSMark de Wever if (*__begin != _CharT('{')) [[likely]] { 448d7444d9fSMark de Wever __ctx.advance_to(_VSTD::move(__out_it)); 449d7444d9fSMark de Wever __begin = 450d7444d9fSMark de Wever __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 451d7444d9fSMark de Wever __out_it = __ctx.out(); 452d7444d9fSMark de Wever 453d7444d9fSMark de Wever // The output is written and __begin points to the next character. So 454d7444d9fSMark de Wever // start the next iteration. 455d7444d9fSMark de Wever continue; 456d7444d9fSMark de Wever } 457d7444d9fSMark de Wever // The string is an escape character. 458d7444d9fSMark de Wever break; 459d7444d9fSMark de Wever 460d7444d9fSMark de Wever case _CharT('}'): 461d7444d9fSMark de Wever ++__begin; 462d7444d9fSMark de Wever if (__begin == __end || *__begin != _CharT('}')) 463d7444d9fSMark de Wever __throw_format_error( 464d7444d9fSMark de Wever "The format string contains an invalid escape sequence"); 465d7444d9fSMark de Wever 466d7444d9fSMark de Wever break; 467d7444d9fSMark de Wever } 468d7444d9fSMark de Wever 469d7444d9fSMark de Wever // Copy the character to the output verbatim. 470d7444d9fSMark de Wever *__out_it++ = *__begin++; 471d7444d9fSMark de Wever } 472d7444d9fSMark de Wever return __out_it; 473d7444d9fSMark de Wever} 474d7444d9fSMark de Wever 475d7444d9fSMark de Wever} // namespace __format 476d7444d9fSMark de Wever 477aed5ddf8SMark de Wevertemplate <class _CharT, class... _Args> 478*13249036SMark de Weverstruct _LIBCPP_TEMPLATE_VIS basic_format_string { 479aed5ddf8SMark de Wever template <class _Tp> 480aed5ddf8SMark de Wever requires convertible_to<const _Tp&, basic_string_view<_CharT>> 481*13249036SMark de Wever consteval basic_format_string(const _Tp& __str) : __str_{__str} { 482aed5ddf8SMark de Wever __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 483aed5ddf8SMark de Wever _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 484aed5ddf8SMark de Wever } 485aed5ddf8SMark de Wever 486*13249036SMark de Wever _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { 487*13249036SMark de Wever return __str_; 488*13249036SMark de Wever } 489*13249036SMark de Wever 490aed5ddf8SMark de Weverprivate: 491*13249036SMark de Wever basic_string_view<_CharT> __str_; 492*13249036SMark de Wever 493aed5ddf8SMark de Wever using _Context = __format::__compile_time_basic_format_context<_CharT>; 494aed5ddf8SMark de Wever 495aed5ddf8SMark de Wever static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 496aed5ddf8SMark de Wever __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 497aed5ddf8SMark de Wever 498aed5ddf8SMark de Wever // TODO FMT remove this work-around when the AIX ICE has been resolved. 499aed5ddf8SMark de Wever# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 500aed5ddf8SMark de Wever template <class _Tp> 501aed5ddf8SMark de Wever static constexpr __format::__compile_time_handle<_CharT> __get_handle() { 502aed5ddf8SMark de Wever __format::__compile_time_handle<_CharT> __handle; 503aed5ddf8SMark de Wever if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 504aed5ddf8SMark de Wever __handle.template __enable<_Tp>(); 505aed5ddf8SMark de Wever 506aed5ddf8SMark de Wever return __handle; 507aed5ddf8SMark de Wever } 508aed5ddf8SMark de Wever 509aed5ddf8SMark de Wever static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ 510aed5ddf8SMark de Wever __get_handle<_Args>()...}; 511aed5ddf8SMark de Wever# else 512aed5ddf8SMark de Wever static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 513aed5ddf8SMark de Wever using _Tp = remove_cvref_t<_Args>; 514aed5ddf8SMark de Wever __format::__compile_time_handle<_CharT> __handle; 515aed5ddf8SMark de Wever if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 516aed5ddf8SMark de Wever __handle.template __enable<_Tp>(); 517aed5ddf8SMark de Wever 518aed5ddf8SMark de Wever return __handle; 519aed5ddf8SMark de Wever }()...}; 520aed5ddf8SMark de Wever# endif 521aed5ddf8SMark de Wever}; 522aed5ddf8SMark de Wever 523aed5ddf8SMark de Wevertemplate <class... _Args> 524*13249036SMark de Weverusing format_string = basic_format_string<char, type_identity_t<_Args>...>; 525aed5ddf8SMark de Wever 526aed5ddf8SMark de Wever#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 527aed5ddf8SMark de Wevertemplate <class... _Args> 528*13249036SMark de Weverusing wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; 529aed5ddf8SMark de Wever#endif 530aed5ddf8SMark de Wever 5310e9979afSMark de Wevertemplate <class _OutIt, class _CharT, class _FormatOutIt> 532d7444d9fSMark de Weverrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 5330e9979afSMark de Wever __vformat_to( 5340e9979afSMark de Wever _OutIt __out_it, basic_string_view<_CharT> __fmt, 5350e9979afSMark de Wever basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 5360e9979afSMark de Wever if constexpr (same_as<_OutIt, _FormatOutIt>) 5370e9979afSMark de Wever return _VSTD::__format::__vformat_to( 538d7444d9fSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 539d7444d9fSMark de Wever _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 5400e9979afSMark de Wever else { 541555214cbSMark de Wever __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 5420e9979afSMark de Wever _VSTD::__format::__vformat_to( 5430e9979afSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 544555214cbSMark de Wever _VSTD::__format_context_create(__buffer.make_output_iterator(), 545555214cbSMark de Wever __args)); 546555214cbSMark de Wever return _VSTD::move(__buffer).out(); 5470e9979afSMark de Wever } 548d7444d9fSMark de Wever} 549d7444d9fSMark de Wever 550f0c06c04SMark de Wever// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 551f0c06c04SMark de Wever// https://reviews.llvm.org/D110499#inline-1180704 552f0c06c04SMark de Wever// TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 553d7444d9fSMark de Wevertemplate <output_iterator<const char&> _OutIt> 5540e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5550e9979afSMark de Wevervformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 556d7444d9fSMark de Wever return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 557d7444d9fSMark de Wever} 558d7444d9fSMark de Wever 559f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 560d7444d9fSMark de Wevertemplate <output_iterator<const wchar_t&> _OutIt> 5610e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5620e9979afSMark de Wevervformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 563d7444d9fSMark de Wever return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 564d7444d9fSMark de Wever} 565f4c1258dSLouis Dionne#endif 566d7444d9fSMark de Wever 567d7444d9fSMark de Wevertemplate <output_iterator<const char&> _OutIt, class... _Args> 5680e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 569*13249036SMark de Weverformat_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { 570*13249036SMark de Wever return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), 5710e9979afSMark de Wever _VSTD::make_format_args(__args...)); 572d7444d9fSMark de Wever} 573d7444d9fSMark de Wever 574f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 575d7444d9fSMark de Wevertemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 5760e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 577*13249036SMark de Weverformat_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { 578*13249036SMark de Wever return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), 5790e9979afSMark de Wever _VSTD::make_wformat_args(__args...)); 580d7444d9fSMark de Wever} 581f4c1258dSLouis Dionne#endif 582d7444d9fSMark de Wever 5830e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 584d7444d9fSMark de Wevervformat(string_view __fmt, format_args __args) { 585d7444d9fSMark de Wever string __res; 586d7444d9fSMark de Wever _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 587d7444d9fSMark de Wever return __res; 588d7444d9fSMark de Wever} 589d7444d9fSMark de Wever 590f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 5910e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 592d7444d9fSMark de Wevervformat(wstring_view __fmt, wformat_args __args) { 593d7444d9fSMark de Wever wstring __res; 594d7444d9fSMark de Wever _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 595d7444d9fSMark de Wever return __res; 596d7444d9fSMark de Wever} 597f4c1258dSLouis Dionne#endif 598d7444d9fSMark de Wever 599d7444d9fSMark de Wevertemplate <class... _Args> 600*13249036SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, 601606e2808SMark de Wever _Args&&... __args) { 602*13249036SMark de Wever return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); 603d7444d9fSMark de Wever} 604d7444d9fSMark de Wever 605f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 606d7444d9fSMark de Wevertemplate <class... _Args> 6070e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 608*13249036SMark de Weverformat(wformat_string<_Args...> __fmt, _Args&&... __args) { 609*13249036SMark de Wever return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); 610d7444d9fSMark de Wever} 611f4c1258dSLouis Dionne#endif 612d7444d9fSMark de Wever 613f0c06c04SMark de Wevertemplate <class _Context, class _OutIt, class _CharT> 614f0c06c04SMark de Wever_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 615f0c06c04SMark de Wever basic_string_view<_CharT> __fmt, 616f0c06c04SMark de Wever basic_format_args<_Context> __args) { 617f0c06c04SMark de Wever __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 618f0c06c04SMark de Wever _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 619f0c06c04SMark de Wever _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 620f0c06c04SMark de Wever return _VSTD::move(__buffer).result(); 621f0c06c04SMark de Wever} 622f0c06c04SMark de Wever 623d7444d9fSMark de Wevertemplate <output_iterator<const char&> _OutIt, class... _Args> 624f0c06c04SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 625*13249036SMark de Weverformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { 626*13249036SMark de Wever return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); 627d7444d9fSMark de Wever} 628d7444d9fSMark de Wever 629f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 630d7444d9fSMark de Wevertemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 631aed5ddf8SMark de Wever_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 632*13249036SMark de Weverformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, 633606e2808SMark de Wever _Args&&... __args) { 634*13249036SMark de Wever return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); 635d7444d9fSMark de Wever} 636f4c1258dSLouis Dionne#endif 637d7444d9fSMark de Wever 638fb9a692bSMark de Wevertemplate <class _CharT> 639fb9a692bSMark de Wever_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 640fb9a692bSMark de Wever __format::__formatted_size_buffer<_CharT> __buffer; 641fb9a692bSMark de Wever _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 642fb9a692bSMark de Wever _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 643fb9a692bSMark de Wever return _VSTD::move(__buffer).result(); 644fb9a692bSMark de Wever} 645fb9a692bSMark de Wever 646d7444d9fSMark de Wevertemplate <class... _Args> 647aed5ddf8SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 648*13249036SMark de Weverformatted_size(format_string<_Args...> __fmt, _Args&&... __args) { 649*13249036SMark de Wever return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); 650d7444d9fSMark de Wever} 651d7444d9fSMark de Wever 652f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 653d7444d9fSMark de Wevertemplate <class... _Args> 654aed5ddf8SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 655*13249036SMark de Weverformatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { 656*13249036SMark de Wever return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); 657d7444d9fSMark de Wever} 658f4c1258dSLouis Dionne#endif 659d7444d9fSMark de Wever 660d7444d9fSMark de Wever#ifndef _LIBCPP_HAS_NO_LOCALIZATION 661d7444d9fSMark de Wever 6620e9979afSMark de Wevertemplate <class _OutIt, class _CharT, class _FormatOutIt> 663d7444d9fSMark de Weverrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 6640e9979afSMark de Wever __vformat_to( 6650e9979afSMark de Wever _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 6660e9979afSMark de Wever basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 6670e9979afSMark de Wever if constexpr (same_as<_OutIt, _FormatOutIt>) 6680e9979afSMark de Wever return _VSTD::__format::__vformat_to( 669d7444d9fSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 670d7444d9fSMark de Wever _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 671d7444d9fSMark de Wever _VSTD::move(__loc))); 6720e9979afSMark de Wever else { 673555214cbSMark de Wever __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 6740e9979afSMark de Wever _VSTD::__format::__vformat_to( 6750e9979afSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 676555214cbSMark de Wever _VSTD::__format_context_create(__buffer.make_output_iterator(), 677555214cbSMark de Wever __args, _VSTD::move(__loc))); 678555214cbSMark de Wever return _VSTD::move(__buffer).out(); 6790e9979afSMark de Wever } 680d7444d9fSMark de Wever} 681d7444d9fSMark de Wever 682d7444d9fSMark de Wevertemplate <output_iterator<const char&> _OutIt> 6830e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6840e9979afSMark de Wever _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 685d7444d9fSMark de Wever return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 686d7444d9fSMark de Wever __args); 687d7444d9fSMark de Wever} 688d7444d9fSMark de Wever 689f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 690d7444d9fSMark de Wevertemplate <output_iterator<const wchar_t&> _OutIt> 6910e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6920e9979afSMark de Wever _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 693d7444d9fSMark de Wever return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 694d7444d9fSMark de Wever __args); 695d7444d9fSMark de Wever} 696f4c1258dSLouis Dionne#endif 697d7444d9fSMark de Wever 698d7444d9fSMark de Wevertemplate <output_iterator<const char&> _OutIt, class... _Args> 699aed5ddf8SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 700*13249036SMark de Weverformat_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 701*13249036SMark de Wever return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), 7020e9979afSMark de Wever _VSTD::make_format_args(__args...)); 703d7444d9fSMark de Wever} 704d7444d9fSMark de Wever 705f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 706d7444d9fSMark de Wevertemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 707aed5ddf8SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 708*13249036SMark de Weverformat_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 709*13249036SMark de Wever return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), 7100e9979afSMark de Wever _VSTD::make_wformat_args(__args...)); 711d7444d9fSMark de Wever} 712f4c1258dSLouis Dionne#endif 713d7444d9fSMark de Wever 7140e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 715d7444d9fSMark de Wevervformat(locale __loc, string_view __fmt, format_args __args) { 716d7444d9fSMark de Wever string __res; 717d7444d9fSMark de Wever _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 718d7444d9fSMark de Wever __args); 719d7444d9fSMark de Wever return __res; 720d7444d9fSMark de Wever} 721d7444d9fSMark de Wever 722f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 7230e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 724d7444d9fSMark de Wevervformat(locale __loc, wstring_view __fmt, wformat_args __args) { 725d7444d9fSMark de Wever wstring __res; 726d7444d9fSMark de Wever _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 727d7444d9fSMark de Wever __args); 728d7444d9fSMark de Wever return __res; 729d7444d9fSMark de Wever} 730f4c1258dSLouis Dionne#endif 731d7444d9fSMark de Wever 732d7444d9fSMark de Wevertemplate <class... _Args> 733aed5ddf8SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, 734*13249036SMark de Wever format_string<_Args...> __fmt, 735606e2808SMark de Wever _Args&&... __args) { 736*13249036SMark de Wever return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), 737d7444d9fSMark de Wever _VSTD::make_format_args(__args...)); 738d7444d9fSMark de Wever} 739d7444d9fSMark de Wever 740f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 741d7444d9fSMark de Wevertemplate <class... _Args> 7420e9979afSMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 743*13249036SMark de Weverformat(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 744*13249036SMark de Wever return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), 745d7444d9fSMark de Wever _VSTD::make_wformat_args(__args...)); 746d7444d9fSMark de Wever} 747f4c1258dSLouis Dionne#endif 748d7444d9fSMark de Wever 749f0c06c04SMark de Wevertemplate <class _Context, class _OutIt, class _CharT> 750f0c06c04SMark de Wever_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 751f0c06c04SMark de Wever locale __loc, basic_string_view<_CharT> __fmt, 752f0c06c04SMark de Wever basic_format_args<_Context> __args) { 753f0c06c04SMark de Wever __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 754f0c06c04SMark de Wever _VSTD::__format::__vformat_to( 755f0c06c04SMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 756f0c06c04SMark de Wever _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 757f0c06c04SMark de Wever return _VSTD::move(__buffer).result(); 758f0c06c04SMark de Wever} 759f0c06c04SMark de Wever 760d7444d9fSMark de Wevertemplate <output_iterator<const char&> _OutIt, class... _Args> 761f0c06c04SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 762*13249036SMark de Weverformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, 763606e2808SMark de Wever _Args&&... __args) { 764*13249036SMark de Wever return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), 765d7444d9fSMark de Wever _VSTD::make_format_args(__args...)); 766d7444d9fSMark de Wever} 767d7444d9fSMark de Wever 768f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 769d7444d9fSMark de Wevertemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 770f0c06c04SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 771*13249036SMark de Weverformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, 772606e2808SMark de Wever _Args&&... __args) { 773*13249036SMark de Wever return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), 774d7444d9fSMark de Wever _VSTD::make_wformat_args(__args...)); 775d7444d9fSMark de Wever} 776f4c1258dSLouis Dionne#endif 777d7444d9fSMark de Wever 778fb9a692bSMark de Wevertemplate <class _CharT> 779fb9a692bSMark de Wever_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 780fb9a692bSMark de Wever __format::__formatted_size_buffer<_CharT> __buffer; 781fb9a692bSMark de Wever _VSTD::__format::__vformat_to( 782fb9a692bSMark de Wever basic_format_parse_context{__fmt, __args.__size()}, 783fb9a692bSMark de Wever _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 784fb9a692bSMark de Wever return _VSTD::move(__buffer).result(); 785fb9a692bSMark de Wever} 786fb9a692bSMark de Wever 787d7444d9fSMark de Wevertemplate <class... _Args> 788aed5ddf8SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 789*13249036SMark de Weverformatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { 790*13249036SMark de Wever return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); 791d7444d9fSMark de Wever} 792d7444d9fSMark de Wever 793f4c1258dSLouis Dionne#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 794d7444d9fSMark de Wevertemplate <class... _Args> 795aed5ddf8SMark de Wever_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 796*13249036SMark de Weverformatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { 797*13249036SMark de Wever return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); 798d7444d9fSMark de Wever} 799f4c1258dSLouis Dionne#endif 800d7444d9fSMark de Wever 801ad2b7a14SLouis Dionne#endif // _LIBCPP_HAS_NO_LOCALIZATION 802d7444d9fSMark de Wever 8030922ce56SMark de Wever#endif //_LIBCPP_STD_VER > 17 8040922ce56SMark de Wever 8050922ce56SMark de Wever_LIBCPP_END_NAMESPACE_STD 8060922ce56SMark de Wever 807d618a1ccSMark de Wever#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 808d618a1ccSMark de Wever 809081c1db0SMark de Wever#endif // _LIBCPP_FORMAT 810