1fe6060f1SDimitry Andric// -*- C++ -*- 2349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric// 4fe6060f1SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric// 8fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 9fe6060f1SDimitry Andric 10fe6060f1SDimitry Andric#ifndef _LIBCPP_FORMAT 11fe6060f1SDimitry Andric#define _LIBCPP_FORMAT 12fe6060f1SDimitry Andric 13fe6060f1SDimitry Andric/* 14fe6060f1SDimitry Andric 15fe6060f1SDimitry Andricnamespace std { 16349cc55cSDimitry Andric // [format.context], class template basic_format_context 1704eeddc0SDimitry Andric template<class Out, class charT> class basic_format_context; 18349cc55cSDimitry Andric using format_context = basic_format_context<unspecified, char>; 19349cc55cSDimitry Andric using wformat_context = basic_format_context<unspecified, wchar_t>; 20349cc55cSDimitry Andric 21349cc55cSDimitry Andric // [format.args], class template basic_format_args 2204eeddc0SDimitry Andric template<class Context> class basic_format_args; 23349cc55cSDimitry Andric using format_args = basic_format_args<format_context>; 24349cc55cSDimitry Andric using wformat_args = basic_format_args<wformat_context>; 25349cc55cSDimitry Andric 26*81ad6265SDimitry Andric // [format.fmt.string], class template basic-format-string 27*81ad6265SDimitry Andric template<class charT, class... Args> 28*81ad6265SDimitry Andric struct basic-format-string; // exposition only 29*81ad6265SDimitry Andric 30*81ad6265SDimitry Andric template<class... Args> 31*81ad6265SDimitry Andric using format-string = // exposition only 32*81ad6265SDimitry Andric basic-format-string<char, type_identity_t<Args>...>; 33*81ad6265SDimitry Andric template<class... Args> 34*81ad6265SDimitry Andric using wformat-string = // exposition only 35*81ad6265SDimitry Andric basic-format-string<wchar_t, type_identity_t<Args>...>; 36*81ad6265SDimitry Andric 37349cc55cSDimitry Andric // [format.functions], formatting functions 38349cc55cSDimitry Andric template<class... Args> 39*81ad6265SDimitry Andric string format(format-string<Args...> fmt, const Args&... args); 40349cc55cSDimitry Andric template<class... Args> 41*81ad6265SDimitry Andric wstring format(wformat-string<Args...> fmt, const Args&... args); 42349cc55cSDimitry Andric template<class... Args> 43*81ad6265SDimitry Andric string format(const locale& loc, format-string<Args...> fmt, const Args&... args); 44349cc55cSDimitry Andric template<class... Args> 45*81ad6265SDimitry Andric wstring format(const locale& loc, wformat-string<Args...> fmt, const 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*81ad6265SDimitry Andric Out format_to(Out out, format-string<Args...> fmt, const Args&... args); 54349cc55cSDimitry Andric template<class Out, class... Args> 55*81ad6265SDimitry Andric Out format_to(Out out, wformat-string<Args...> fmt, const Args&... args); 56349cc55cSDimitry Andric template<class Out, class... Args> 57*81ad6265SDimitry Andric Out format_to(Out out, const locale& loc, format-string<Args...> fmt, const Args&... args); 58349cc55cSDimitry Andric template<class Out, class... Args> 59*81ad6265SDimitry Andric Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, const 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*81ad6265SDimitry Andric format-string<Args...> fmt, const 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*81ad6265SDimitry Andric wformat-string<Args...> fmt, const 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, 84*81ad6265SDimitry Andric const locale& loc, format-string<Args...> fmt, 85349cc55cSDimitry Andric const 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, 88*81ad6265SDimitry Andric const locale& loc, wformat-string<Args...> fmt, 89349cc55cSDimitry Andric const Args&... args); 90349cc55cSDimitry Andric 91349cc55cSDimitry Andric template<class... Args> 92*81ad6265SDimitry Andric size_t formatted_size(format-string<Args...> fmt, const Args&... args); 93349cc55cSDimitry Andric template<class... Args> 94*81ad6265SDimitry Andric size_t formatted_size(wformat-string<Args...> fmt, const Args&... args); 95349cc55cSDimitry Andric template<class... Args> 96*81ad6265SDimitry Andric size_t formatted_size(const locale& loc, format-string<Args...> fmt, const Args&... args); 97349cc55cSDimitry Andric template<class... Args> 98*81ad6265SDimitry Andric size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, const 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...> 120349cc55cSDimitry Andric make_format_args(const Args&... args); 121349cc55cSDimitry Andric template<class... Args> 122349cc55cSDimitry Andric format-arg-store<wformat_context, Args...> 123349cc55cSDimitry Andric make_wformat_args(const Args&... args); 124349cc55cSDimitry Andric 125fe6060f1SDimitry Andric // [format.error], class format_error 12604eeddc0SDimitry Andric class format_error; 127fe6060f1SDimitry Andric} 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric*/ 130fe6060f1SDimitry Andric 131*81ad6265SDimitry 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 137*81ad6265SDimitry Andric#include <__algorithm/clamp.h> 138fe6060f1SDimitry Andric#include <__config> 139349cc55cSDimitry Andric#include <__debug> 140*81ad6265SDimitry Andric#include <__format/buffer.h> 141*81ad6265SDimitry Andric#include <__format/concepts.h> 142*81ad6265SDimitry Andric#include <__format/enable_insertable.h> 143349cc55cSDimitry Andric#include <__format/format_arg.h> 144*81ad6265SDimitry Andric#include <__format/format_arg_store.h> 145349cc55cSDimitry Andric#include <__format/format_args.h> 146349cc55cSDimitry Andric#include <__format/format_context.h> 147fe6060f1SDimitry Andric#include <__format/format_error.h> 148349cc55cSDimitry Andric#include <__format/format_fwd.h> 149fe6060f1SDimitry Andric#include <__format/format_parse_context.h> 150349cc55cSDimitry Andric#include <__format/format_string.h> 151349cc55cSDimitry Andric#include <__format/format_to_n_result.h> 152349cc55cSDimitry Andric#include <__format/formatter.h> 153349cc55cSDimitry Andric#include <__format/formatter_bool.h> 154349cc55cSDimitry Andric#include <__format/formatter_char.h> 15504eeddc0SDimitry Andric#include <__format/formatter_floating_point.h> 156349cc55cSDimitry Andric#include <__format/formatter_integer.h> 15704eeddc0SDimitry Andric#include <__format/formatter_pointer.h> 158349cc55cSDimitry Andric#include <__format/formatter_string.h> 159349cc55cSDimitry Andric#include <__format/parser_std_format_spec.h> 160*81ad6265SDimitry Andric#include <__iterator/back_insert_iterator.h> 161*81ad6265SDimitry 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 193*81ad6265SDimitry Andric// TODO FMT This helper wrapper can probably be removed after P2418 has been 194*81ad6265SDimitry Andric// implemented. 195349cc55cSDimitry Andrictemplate <class _Context, class... _Args> 196349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> 197*81ad6265SDimitry Andric__make_format_args(_Args&&... __args) { 198*81ad6265SDimitry Andric return _VSTD::__format_arg_store<_Context, _Args...>( 199*81ad6265SDimitry Andric _VSTD::forward<_Args>(__args)...); 200*81ad6265SDimitry Andric} 201*81ad6265SDimitry Andric 202*81ad6265SDimitry Andric// TODO FMT After P2418 specify the return type instead of using auto. 203*81ad6265SDimitry Andrictemplate <class _Context = format_context, class... _Args> 204*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI auto make_format_args(const _Args&... __args) { 205*81ad6265SDimitry Andric return _VSTD::__make_format_args<_Context>(__args...); 206349cc55cSDimitry Andric} 207349cc55cSDimitry Andric 208349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 209*81ad6265SDimitry Andric// TODO FMT After P2418 specify the return type instead of using auto. 210349cc55cSDimitry Andrictemplate <class... _Args> 211*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI auto make_wformat_args(const _Args&... __args) { 212349cc55cSDimitry Andric return _VSTD::make_format_args<wformat_context>(__args...); 213349cc55cSDimitry Andric} 214349cc55cSDimitry Andric#endif 215349cc55cSDimitry Andric 216349cc55cSDimitry Andricnamespace __format { 217349cc55cSDimitry Andric 218*81ad6265SDimitry Andric/// Helper class parse and handle argument. 219*81ad6265SDimitry Andric/// 220*81ad6265SDimitry Andric/// When parsing a handle which is not enabled the code is ill-formed. 221*81ad6265SDimitry Andric/// This helper uses the parser of the appropriate formatter for the stored type. 222*81ad6265SDimitry Andrictemplate <class _CharT> 223*81ad6265SDimitry Andricclass _LIBCPP_TEMPLATE_VIS __compile_time_handle { 224*81ad6265SDimitry Andricpublic: 225*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI 226*81ad6265SDimitry Andric constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } 227*81ad6265SDimitry Andric 228*81ad6265SDimitry Andric template <class _Tp> 229*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { 230*81ad6265SDimitry Andric __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { 231*81ad6265SDimitry Andric formatter<_Tp, _CharT> __f; 232*81ad6265SDimitry Andric __parse_ctx.advance_to(__f.parse(__parse_ctx)); 233*81ad6265SDimitry Andric }; 234*81ad6265SDimitry Andric } 235*81ad6265SDimitry Andric 236*81ad6265SDimitry Andric // Before calling __parse the proper handler needs to be set with __enable. 237*81ad6265SDimitry Andric // The default handler isn't a core constant expression. 238*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() 239*81ad6265SDimitry Andric : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {} 240*81ad6265SDimitry Andric 241*81ad6265SDimitry Andricprivate: 242*81ad6265SDimitry Andric void (*__parse_)(basic_format_parse_context<_CharT>&); 243*81ad6265SDimitry Andric}; 244*81ad6265SDimitry Andric 245*81ad6265SDimitry Andric// Dummy format_context only providing the parts used during constant 246*81ad6265SDimitry Andric// validation of the basic-format-string. 247*81ad6265SDimitry Andrictemplate <class _CharT> 248*81ad6265SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { 249*81ad6265SDimitry Andricpublic: 250*81ad6265SDimitry Andric using char_type = _CharT; 251*81ad6265SDimitry Andric 252*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context( 253*81ad6265SDimitry Andric const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size) 254*81ad6265SDimitry Andric : __args_(__args), __handles_(__handles), __size_(__size) {} 255*81ad6265SDimitry Andric 256*81ad6265SDimitry Andric // During the compile-time validation nothing needs to be written. 257*81ad6265SDimitry Andric // Therefore all operations of this iterator are a NOP. 258*81ad6265SDimitry Andric struct iterator { 259*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; } 260*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; } 261*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; } 262*81ad6265SDimitry Andric }; 263*81ad6265SDimitry Andric 264*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { 265*81ad6265SDimitry Andric if (__id >= __size_) 266*81ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 267*81ad6265SDimitry Andric return __args_[__id]; 268*81ad6265SDimitry Andric } 269*81ad6265SDimitry Andric 270*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { 271*81ad6265SDimitry Andric if (__id >= __size_) 272*81ad6265SDimitry Andric __throw_format_error("Argument index out of bounds"); 273*81ad6265SDimitry Andric return __handles_[__id]; 274*81ad6265SDimitry Andric } 275*81ad6265SDimitry Andric 276*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; } 277*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {} 278*81ad6265SDimitry Andric 279*81ad6265SDimitry Andricprivate: 280*81ad6265SDimitry Andric const __arg_t* __args_; 281*81ad6265SDimitry Andric const __compile_time_handle<_CharT>* __handles_; 282*81ad6265SDimitry Andric size_t __size_; 283*81ad6265SDimitry Andric}; 284*81ad6265SDimitry Andric 285*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI 286*81ad6265SDimitry Andricconstexpr void __compile_time_validate_integral(__arg_t __type) { 287*81ad6265SDimitry Andric switch (__type) { 288*81ad6265SDimitry Andric case __arg_t::__int: 289*81ad6265SDimitry Andric case __arg_t::__long_long: 290*81ad6265SDimitry Andric case __arg_t::__i128: 291*81ad6265SDimitry Andric case __arg_t::__unsigned: 292*81ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 293*81ad6265SDimitry Andric case __arg_t::__u128: 294*81ad6265SDimitry Andric return; 295*81ad6265SDimitry Andric 296*81ad6265SDimitry Andric default: 297*81ad6265SDimitry Andric __throw_format_error("Argument isn't an integral type"); 298*81ad6265SDimitry Andric } 299*81ad6265SDimitry Andric} 300*81ad6265SDimitry Andric 301*81ad6265SDimitry Andric// _HasPrecision does the formatter have a precision? 302*81ad6265SDimitry Andrictemplate <class _CharT, class _Tp, bool _HasPrecision = false> 303*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void 304*81ad6265SDimitry Andric__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, 305*81ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx) { 306*81ad6265SDimitry Andric formatter<_Tp, _CharT> __formatter; 307*81ad6265SDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 308*81ad6265SDimitry Andric // [format.string.std]/7 309*81ad6265SDimitry Andric // ... If the corresponding formatting argument is not of integral type, or 310*81ad6265SDimitry Andric // its value is negative for precision or non-positive for width, an 311*81ad6265SDimitry Andric // exception of type format_error is thrown. 312*81ad6265SDimitry Andric // 313*81ad6265SDimitry Andric // Validate whether the arguments are integrals. 314*81ad6265SDimitry Andric if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) { 315*81ad6265SDimitry Andric // TODO FMT Remove this when parser v1 has been phased out. 316*81ad6265SDimitry Andric if (__formatter.__width_needs_substitution()) 317*81ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__width)); 318*81ad6265SDimitry Andric 319*81ad6265SDimitry Andric if constexpr (_HasPrecision) 320*81ad6265SDimitry Andric if (__formatter.__precision_needs_substitution()) 321*81ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision)); 322*81ad6265SDimitry Andric } else { 323*81ad6265SDimitry Andric if (__formatter.__parser_.__width_as_arg_) 324*81ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); 325*81ad6265SDimitry Andric 326*81ad6265SDimitry Andric if constexpr (_HasPrecision) 327*81ad6265SDimitry Andric if (__formatter.__parser_.__precision_as_arg_) 328*81ad6265SDimitry Andric __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); 329*81ad6265SDimitry Andric } 330*81ad6265SDimitry Andric} 331*81ad6265SDimitry Andric 332*81ad6265SDimitry Andrictemplate <class _CharT> 333*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx, 334*81ad6265SDimitry Andric __compile_time_basic_format_context<_CharT>& __ctx, 335*81ad6265SDimitry Andric __arg_t __type) { 336*81ad6265SDimitry Andric switch (__type) { 337*81ad6265SDimitry Andric case __arg_t::__none: 338*81ad6265SDimitry Andric __throw_format_error("Invalid argument"); 339*81ad6265SDimitry Andric case __arg_t::__boolean: 340*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); 341*81ad6265SDimitry Andric case __arg_t::__char_type: 342*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx); 343*81ad6265SDimitry Andric case __arg_t::__int: 344*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx); 345*81ad6265SDimitry Andric case __arg_t::__long_long: 346*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); 347*81ad6265SDimitry Andric case __arg_t::__i128: 348*81ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 349*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); 350*81ad6265SDimitry Andric# else 351*81ad6265SDimitry Andric __throw_format_error("Invalid argument"); 352*81ad6265SDimitry Andric# endif 353*81ad6265SDimitry Andric return; 354*81ad6265SDimitry Andric case __arg_t::__unsigned: 355*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx); 356*81ad6265SDimitry Andric case __arg_t::__unsigned_long_long: 357*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); 358*81ad6265SDimitry Andric case __arg_t::__u128: 359*81ad6265SDimitry Andric# ifndef _LIBCPP_HAS_NO_INT128 360*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); 361*81ad6265SDimitry Andric# else 362*81ad6265SDimitry Andric __throw_format_error("Invalid argument"); 363*81ad6265SDimitry Andric# endif 364*81ad6265SDimitry Andric return; 365*81ad6265SDimitry Andric case __arg_t::__float: 366*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx); 367*81ad6265SDimitry Andric case __arg_t::__double: 368*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx); 369*81ad6265SDimitry Andric case __arg_t::__long_double: 370*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx); 371*81ad6265SDimitry Andric case __arg_t::__const_char_type_ptr: 372*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx); 373*81ad6265SDimitry Andric case __arg_t::__string_view: 374*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx); 375*81ad6265SDimitry Andric case __arg_t::__ptr: 376*81ad6265SDimitry Andric return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); 377*81ad6265SDimitry Andric case __arg_t::__handle: 378*81ad6265SDimitry Andric __throw_format_error("Handle should use __compile_time_validate_handle_argument"); 379*81ad6265SDimitry Andric } 380*81ad6265SDimitry Andric __throw_format_error("Invalid argument"); 381*81ad6265SDimitry Andric} 382*81ad6265SDimitry Andric 383349cc55cSDimitry Andrictemplate <class _CharT, class _ParseCtx, class _Ctx> 384*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 385349cc55cSDimitry Andric__handle_replacement_field(const _CharT* __begin, const _CharT* __end, 386349cc55cSDimitry Andric _ParseCtx& __parse_ctx, _Ctx& __ctx) { 387349cc55cSDimitry Andric __format::__parse_number_result __r = 388349cc55cSDimitry Andric __format::__parse_arg_id(__begin, __end, __parse_ctx); 389349cc55cSDimitry Andric 390349cc55cSDimitry Andric switch (*__r.__ptr) { 391349cc55cSDimitry Andric case _CharT(':'): 392349cc55cSDimitry Andric // The arg-id has a format-specifier, advance the input to the format-spec. 393349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr + 1); 394349cc55cSDimitry Andric break; 395349cc55cSDimitry Andric case _CharT('}'): 396349cc55cSDimitry Andric // The arg-id has no format-specifier. 397349cc55cSDimitry Andric __parse_ctx.advance_to(__r.__ptr); 398349cc55cSDimitry Andric break; 399349cc55cSDimitry Andric default: 400349cc55cSDimitry Andric __throw_format_error( 401349cc55cSDimitry Andric "The replacement field arg-id should terminate at a ':' or '}'"); 402349cc55cSDimitry Andric } 403349cc55cSDimitry Andric 404*81ad6265SDimitry Andric if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { 405*81ad6265SDimitry Andric __arg_t __type = __ctx.arg(__r.__value); 406*81ad6265SDimitry Andric if (__type == __arg_t::__handle) 407*81ad6265SDimitry Andric __ctx.__handle(__r.__value).__parse(__parse_ctx); 408*81ad6265SDimitry Andric else 409*81ad6265SDimitry Andric __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); 410*81ad6265SDimitry Andric } else 411349cc55cSDimitry Andric _VSTD::visit_format_arg( 412349cc55cSDimitry Andric [&](auto __arg) { 413349cc55cSDimitry Andric if constexpr (same_as<decltype(__arg), monostate>) 414349cc55cSDimitry Andric __throw_format_error("Argument index out of bounds"); 41504eeddc0SDimitry Andric else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) 41604eeddc0SDimitry Andric __arg.format(__parse_ctx, __ctx); 417349cc55cSDimitry Andric else { 418349cc55cSDimitry Andric formatter<decltype(__arg), _CharT> __formatter; 419349cc55cSDimitry Andric __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); 420349cc55cSDimitry Andric __ctx.advance_to(__formatter.format(__arg, __ctx)); 421349cc55cSDimitry Andric } 422349cc55cSDimitry Andric }, 423349cc55cSDimitry Andric __ctx.arg(__r.__value)); 424349cc55cSDimitry Andric 425349cc55cSDimitry Andric __begin = __parse_ctx.begin(); 426349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 427349cc55cSDimitry Andric __throw_format_error("The replacement field misses a terminating '}'"); 428349cc55cSDimitry Andric 429349cc55cSDimitry Andric return ++__begin; 430349cc55cSDimitry Andric} 431349cc55cSDimitry Andric 432349cc55cSDimitry Andrictemplate <class _ParseCtx, class _Ctx> 433*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator 434349cc55cSDimitry Andric__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { 435349cc55cSDimitry Andric using _CharT = typename _ParseCtx::char_type; 436349cc55cSDimitry Andric static_assert(same_as<typename _Ctx::char_type, _CharT>); 437349cc55cSDimitry Andric 438349cc55cSDimitry Andric const _CharT* __begin = __parse_ctx.begin(); 439349cc55cSDimitry Andric const _CharT* __end = __parse_ctx.end(); 440349cc55cSDimitry Andric typename _Ctx::iterator __out_it = __ctx.out(); 441349cc55cSDimitry Andric while (__begin != __end) { 442349cc55cSDimitry Andric switch (*__begin) { 443349cc55cSDimitry Andric case _CharT('{'): 444349cc55cSDimitry Andric ++__begin; 445349cc55cSDimitry Andric if (__begin == __end) 446349cc55cSDimitry Andric __throw_format_error("The format string terminates at a '{'"); 447349cc55cSDimitry Andric 448349cc55cSDimitry Andric if (*__begin != _CharT('{')) [[likely]] { 449349cc55cSDimitry Andric __ctx.advance_to(_VSTD::move(__out_it)); 450349cc55cSDimitry Andric __begin = 451349cc55cSDimitry Andric __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); 452349cc55cSDimitry Andric __out_it = __ctx.out(); 453349cc55cSDimitry Andric 454349cc55cSDimitry Andric // The output is written and __begin points to the next character. So 455349cc55cSDimitry Andric // start the next iteration. 456349cc55cSDimitry Andric continue; 457349cc55cSDimitry Andric } 458349cc55cSDimitry Andric // The string is an escape character. 459349cc55cSDimitry Andric break; 460349cc55cSDimitry Andric 461349cc55cSDimitry Andric case _CharT('}'): 462349cc55cSDimitry Andric ++__begin; 463349cc55cSDimitry Andric if (__begin == __end || *__begin != _CharT('}')) 464349cc55cSDimitry Andric __throw_format_error( 465349cc55cSDimitry Andric "The format string contains an invalid escape sequence"); 466349cc55cSDimitry Andric 467349cc55cSDimitry Andric break; 468349cc55cSDimitry Andric } 469349cc55cSDimitry Andric 470349cc55cSDimitry Andric // Copy the character to the output verbatim. 471349cc55cSDimitry Andric *__out_it++ = *__begin++; 472349cc55cSDimitry Andric } 473349cc55cSDimitry Andric return __out_it; 474349cc55cSDimitry Andric} 475349cc55cSDimitry Andric 476349cc55cSDimitry Andric} // namespace __format 477349cc55cSDimitry Andric 478*81ad6265SDimitry Andrictemplate <class _CharT, class... _Args> 479*81ad6265SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __basic_format_string { 480*81ad6265SDimitry Andric basic_string_view<_CharT> __str_; 481*81ad6265SDimitry Andric 482*81ad6265SDimitry Andric template <class _Tp> 483*81ad6265SDimitry Andric requires convertible_to<const _Tp&, basic_string_view<_CharT>> 484*81ad6265SDimitry Andric consteval __basic_format_string(const _Tp& __str) : __str_{__str} { 485*81ad6265SDimitry Andric __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, 486*81ad6265SDimitry Andric _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); 487*81ad6265SDimitry Andric } 488*81ad6265SDimitry Andric 489*81ad6265SDimitry Andricprivate: 490*81ad6265SDimitry Andric using _Context = __format::__compile_time_basic_format_context<_CharT>; 491*81ad6265SDimitry Andric 492*81ad6265SDimitry Andric static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ 493*81ad6265SDimitry Andric __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; 494*81ad6265SDimitry Andric 495*81ad6265SDimitry Andric // TODO FMT remove this work-around when the AIX ICE has been resolved. 496*81ad6265SDimitry Andric# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 497*81ad6265SDimitry Andric template <class _Tp> 498*81ad6265SDimitry Andric static constexpr __format::__compile_time_handle<_CharT> __get_handle() { 499*81ad6265SDimitry Andric __format::__compile_time_handle<_CharT> __handle; 500*81ad6265SDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 501*81ad6265SDimitry Andric __handle.template __enable<_Tp>(); 502*81ad6265SDimitry Andric 503*81ad6265SDimitry Andric return __handle; 504*81ad6265SDimitry Andric } 505*81ad6265SDimitry Andric 506*81ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ 507*81ad6265SDimitry Andric __get_handle<_Args>()...}; 508*81ad6265SDimitry Andric# else 509*81ad6265SDimitry Andric static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { 510*81ad6265SDimitry Andric using _Tp = remove_cvref_t<_Args>; 511*81ad6265SDimitry Andric __format::__compile_time_handle<_CharT> __handle; 512*81ad6265SDimitry Andric if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) 513*81ad6265SDimitry Andric __handle.template __enable<_Tp>(); 514*81ad6265SDimitry Andric 515*81ad6265SDimitry Andric return __handle; 516*81ad6265SDimitry Andric }()...}; 517*81ad6265SDimitry Andric# endif 518*81ad6265SDimitry Andric}; 519*81ad6265SDimitry Andric 520*81ad6265SDimitry Andrictemplate <class... _Args> 521*81ad6265SDimitry Andricusing __format_string_t = __basic_format_string<char, type_identity_t<_Args>...>; 522*81ad6265SDimitry Andric 523*81ad6265SDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 524*81ad6265SDimitry Andrictemplate <class... _Args> 525*81ad6265SDimitry Andricusing __wformat_string_t = __basic_format_string<wchar_t, type_identity_t<_Args>...>; 526*81ad6265SDimitry Andric#endif 527*81ad6265SDimitry Andric 5284824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 529349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 5304824e7fdSDimitry Andric __vformat_to( 5314824e7fdSDimitry Andric _OutIt __out_it, basic_string_view<_CharT> __fmt, 5324824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 5334824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 5344824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 535349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 536349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args)); 5374824e7fdSDimitry Andric else { 538*81ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 5394824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 5404824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 541*81ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 542*81ad6265SDimitry Andric __args)); 543*81ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 5444824e7fdSDimitry Andric } 545349cc55cSDimitry Andric} 546349cc55cSDimitry Andric 547*81ad6265SDimitry Andric// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining 548*81ad6265SDimitry Andric// https://reviews.llvm.org/D110499#inline-1180704 549*81ad6265SDimitry Andric// TODO FMT Evaluate whether we want to file a Clang bug report regarding this. 550349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 5514824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5524824e7fdSDimitry Andricvformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { 553349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 554349cc55cSDimitry Andric} 555349cc55cSDimitry Andric 556349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 557349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 5584824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 5594824e7fdSDimitry Andricvformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { 560349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); 561349cc55cSDimitry Andric} 562349cc55cSDimitry Andric#endif 563349cc55cSDimitry Andric 564349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 5654824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 566*81ad6265SDimitry Andricformat_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, const _Args&... __args) { 567*81ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, 5684824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 569349cc55cSDimitry Andric} 570349cc55cSDimitry Andric 571349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 572349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 5734824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 574*81ad6265SDimitry Andricformat_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, const _Args&... __args) { 575*81ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, 5764824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 577349cc55cSDimitry Andric} 578349cc55cSDimitry Andric#endif 579349cc55cSDimitry Andric 5804824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 581349cc55cSDimitry Andricvformat(string_view __fmt, format_args __args) { 582349cc55cSDimitry Andric string __res; 583349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 584349cc55cSDimitry Andric return __res; 585349cc55cSDimitry Andric} 586349cc55cSDimitry Andric 587349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 5884824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 589349cc55cSDimitry Andricvformat(wstring_view __fmt, wformat_args __args) { 590349cc55cSDimitry Andric wstring __res; 591349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); 592349cc55cSDimitry Andric return __res; 593349cc55cSDimitry Andric} 594349cc55cSDimitry Andric#endif 595349cc55cSDimitry Andric 596349cc55cSDimitry Andrictemplate <class... _Args> 597*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt, 598*81ad6265SDimitry Andric const _Args&... __args) { 599*81ad6265SDimitry Andric return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...)); 600349cc55cSDimitry Andric} 601349cc55cSDimitry Andric 602349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 603349cc55cSDimitry Andrictemplate <class... _Args> 6044824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 605*81ad6265SDimitry Andricformat(__wformat_string_t<_Args...> __fmt, const _Args&... __args) { 606*81ad6265SDimitry Andric return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...)); 607349cc55cSDimitry Andric} 608349cc55cSDimitry Andric#endif 609349cc55cSDimitry Andric 610*81ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 611*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 612*81ad6265SDimitry Andric basic_string_view<_CharT> __fmt, 613*81ad6265SDimitry Andric basic_format_args<_Context> __args) { 614*81ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 615*81ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 616*81ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 617*81ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 618*81ad6265SDimitry Andric} 619*81ad6265SDimitry Andric 620349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 621*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 622*81ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, const _Args&... __args) { 623*81ad6265SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...)); 624349cc55cSDimitry Andric} 625349cc55cSDimitry Andric 626349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 627349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 628349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 629*81ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt, 630349cc55cSDimitry Andric const _Args&... __args) { 631*81ad6265SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...)); 632349cc55cSDimitry Andric} 633349cc55cSDimitry Andric#endif 634349cc55cSDimitry Andric 635*81ad6265SDimitry Andrictemplate <class _CharT> 636*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) { 637*81ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 638*81ad6265SDimitry Andric _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, 639*81ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args)); 640*81ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 641*81ad6265SDimitry Andric} 642*81ad6265SDimitry Andric 643349cc55cSDimitry Andrictemplate <class... _Args> 644*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 645*81ad6265SDimitry Andricformatted_size(__format_string_t<_Args...> __fmt, const _Args&... __args) { 646*81ad6265SDimitry Andric return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); 647349cc55cSDimitry Andric} 648349cc55cSDimitry Andric 649349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 650349cc55cSDimitry Andrictemplate <class... _Args> 651*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 652*81ad6265SDimitry Andricformatted_size(__wformat_string_t<_Args...> __fmt, const _Args&... __args) { 653*81ad6265SDimitry Andric return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); 654349cc55cSDimitry Andric} 655349cc55cSDimitry Andric#endif 656349cc55cSDimitry Andric 657349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION 658349cc55cSDimitry Andric 6594824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt> 660349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt 6614824e7fdSDimitry Andric __vformat_to( 6624824e7fdSDimitry Andric _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, 6634824e7fdSDimitry Andric basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) { 6644824e7fdSDimitry Andric if constexpr (same_as<_OutIt, _FormatOutIt>) 6654824e7fdSDimitry Andric return _VSTD::__format::__vformat_to( 666349cc55cSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 667349cc55cSDimitry Andric _VSTD::__format_context_create(_VSTD::move(__out_it), __args, 668349cc55cSDimitry Andric _VSTD::move(__loc))); 6694824e7fdSDimitry Andric else { 670*81ad6265SDimitry Andric __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; 6714824e7fdSDimitry Andric _VSTD::__format::__vformat_to( 6724824e7fdSDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 673*81ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), 674*81ad6265SDimitry Andric __args, _VSTD::move(__loc))); 675*81ad6265SDimitry Andric return _VSTD::move(__buffer).out(); 6764824e7fdSDimitry Andric } 677349cc55cSDimitry Andric} 678349cc55cSDimitry Andric 679349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt> 6804824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6814824e7fdSDimitry Andric _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { 682349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 683349cc55cSDimitry Andric __args); 684349cc55cSDimitry Andric} 685349cc55cSDimitry Andric 686349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 687349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt> 6884824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( 6894824e7fdSDimitry Andric _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { 690349cc55cSDimitry Andric return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, 691349cc55cSDimitry Andric __args); 692349cc55cSDimitry Andric} 693349cc55cSDimitry Andric#endif 694349cc55cSDimitry Andric 695349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 696*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 697*81ad6265SDimitry Andricformat_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, const _Args&... __args) { 698*81ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, 6994824e7fdSDimitry Andric _VSTD::make_format_args(__args...)); 700349cc55cSDimitry Andric} 701349cc55cSDimitry Andric 702349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 703349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 704*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt 705*81ad6265SDimitry Andricformat_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, const _Args&... __args) { 706*81ad6265SDimitry Andric return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, 7074824e7fdSDimitry Andric _VSTD::make_wformat_args(__args...)); 708349cc55cSDimitry Andric} 709349cc55cSDimitry Andric#endif 710349cc55cSDimitry Andric 7114824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string 712349cc55cSDimitry Andricvformat(locale __loc, string_view __fmt, format_args __args) { 713349cc55cSDimitry Andric string __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 719349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 7204824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 721349cc55cSDimitry Andricvformat(locale __loc, wstring_view __fmt, wformat_args __args) { 722349cc55cSDimitry Andric wstring __res; 723349cc55cSDimitry Andric _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, 724349cc55cSDimitry Andric __args); 725349cc55cSDimitry Andric return __res; 726349cc55cSDimitry Andric} 727349cc55cSDimitry Andric#endif 728349cc55cSDimitry Andric 729349cc55cSDimitry Andrictemplate <class... _Args> 730*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, 731*81ad6265SDimitry Andric __format_string_t<_Args...> __fmt, 732*81ad6265SDimitry Andric const _Args&... __args) { 733*81ad6265SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, 734349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 735349cc55cSDimitry Andric} 736349cc55cSDimitry Andric 737349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 738349cc55cSDimitry Andrictemplate <class... _Args> 7394824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring 740*81ad6265SDimitry Andricformat(locale __loc, __wformat_string_t<_Args...> __fmt, const _Args&... __args) { 741*81ad6265SDimitry Andric return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, 742349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 743349cc55cSDimitry Andric} 744349cc55cSDimitry Andric#endif 745349cc55cSDimitry Andric 746*81ad6265SDimitry Andrictemplate <class _Context, class _OutIt, class _CharT> 747*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, 748*81ad6265SDimitry Andric locale __loc, basic_string_view<_CharT> __fmt, 749*81ad6265SDimitry Andric basic_format_args<_Context> __args) { 750*81ad6265SDimitry Andric __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n}; 751*81ad6265SDimitry Andric _VSTD::__format::__vformat_to( 752*81ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 753*81ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 754*81ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 755*81ad6265SDimitry Andric} 756*81ad6265SDimitry Andric 757349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args> 758*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 759*81ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt, 760*81ad6265SDimitry Andric const _Args&... __args) { 761*81ad6265SDimitry Andric return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, 762349cc55cSDimitry Andric _VSTD::make_format_args(__args...)); 763349cc55cSDimitry Andric} 764349cc55cSDimitry Andric 765349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 766349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args> 767*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> 768*81ad6265SDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt, 769*81ad6265SDimitry Andric const _Args&... __args) { 770*81ad6265SDimitry Andric return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, 771349cc55cSDimitry Andric _VSTD::make_wformat_args(__args...)); 772349cc55cSDimitry Andric} 773349cc55cSDimitry Andric#endif 774349cc55cSDimitry Andric 775*81ad6265SDimitry Andrictemplate <class _CharT> 776*81ad6265SDimitry Andric_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) { 777*81ad6265SDimitry Andric __format::__formatted_size_buffer<_CharT> __buffer; 778*81ad6265SDimitry Andric _VSTD::__format::__vformat_to( 779*81ad6265SDimitry Andric basic_format_parse_context{__fmt, __args.__size()}, 780*81ad6265SDimitry Andric _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc))); 781*81ad6265SDimitry Andric return _VSTD::move(__buffer).result(); 782*81ad6265SDimitry Andric} 783*81ad6265SDimitry Andric 784349cc55cSDimitry Andrictemplate <class... _Args> 785*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 786*81ad6265SDimitry Andricformatted_size(locale __loc, __format_string_t<_Args...> __fmt, const _Args&... __args) { 787*81ad6265SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); 788349cc55cSDimitry Andric} 789349cc55cSDimitry Andric 790349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 791349cc55cSDimitry Andrictemplate <class... _Args> 792*81ad6265SDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t 793*81ad6265SDimitry Andricformatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, const _Args&... __args) { 794*81ad6265SDimitry Andric return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); 795349cc55cSDimitry Andric} 796349cc55cSDimitry Andric#endif 797349cc55cSDimitry Andric 798349cc55cSDimitry Andric#endif // _LIBCPP_HAS_NO_LOCALIZATION 799349cc55cSDimitry Andric 800fe6060f1SDimitry Andric#endif //_LIBCPP_STD_VER > 17 801fe6060f1SDimitry Andric 802fe6060f1SDimitry Andric_LIBCPP_END_NAMESPACE_STD 803fe6060f1SDimitry Andric 8046e75b2fbSDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) 8056e75b2fbSDimitry Andric 806fe6060f1SDimitry Andric#endif // _LIBCPP_FORMAT 807