1349cc55cSDimitry Andric // -*- C++ -*- 2349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 3349cc55cSDimitry Andric // 4349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7349cc55cSDimitry Andric // 8349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 9349cc55cSDimitry Andric 10349cc55cSDimitry Andric #ifndef _LIBCPP___FORMAT_FORMAT_ARG_H 11349cc55cSDimitry Andric #define _LIBCPP___FORMAT_FORMAT_ARG_H 12349cc55cSDimitry Andric 1381ad6265SDimitry Andric #include <__assert> 14349cc55cSDimitry Andric #include <__concepts/arithmetic.h> 15349cc55cSDimitry Andric #include <__config> 1606c3fb27SDimitry Andric #include <__format/concepts.h> 1704eeddc0SDimitry Andric #include <__format/format_parse_context.h> 1881ad6265SDimitry Andric #include <__functional/invoke.h> 19*0fca6ea1SDimitry Andric #include <__fwd/format.h> 2004eeddc0SDimitry Andric #include <__memory/addressof.h> 2106c3fb27SDimitry Andric #include <__type_traits/conditional.h> 2281ad6265SDimitry Andric #include <__utility/forward.h> 2306c3fb27SDimitry Andric #include <__utility/move.h> 2481ad6265SDimitry Andric #include <__utility/unreachable.h> 25349cc55cSDimitry Andric #include <__variant/monostate.h> 2606c3fb27SDimitry Andric #include <cstdint> 27349cc55cSDimitry Andric #include <string_view> 28349cc55cSDimitry Andric 29349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30349cc55cSDimitry Andric # pragma GCC system_header 31349cc55cSDimitry Andric #endif 32349cc55cSDimitry Andric 33b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 34b3edf446SDimitry Andric #include <__undef_macros> 35b3edf446SDimitry Andric 36349cc55cSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 37349cc55cSDimitry Andric 3806c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric namespace __format { 410eae32dcSDimitry Andric /// The type stored in @ref basic_format_arg. 420eae32dcSDimitry Andric /// 430eae32dcSDimitry Andric /// @note The 128-bit types are unconditionally in the list to avoid the values 440eae32dcSDimitry Andric /// of the enums to depend on the availability of 128-bit integers. 4581ad6265SDimitry Andric /// 4681ad6265SDimitry Andric /// @note The value is stored as a 5-bit value in the __packed_arg_t_bits. This 4781ad6265SDimitry Andric /// limits the maximum number of elements to 32. 4881ad6265SDimitry Andric /// When modifying update the test 4981ad6265SDimitry Andric /// test/libcxx/utilities/format/format.arguments/format.arg/arg_t.compile.pass.cpp 5081ad6265SDimitry Andric /// It could be packed in 4-bits but that means a new type directly becomes an 5181ad6265SDimitry Andric /// ABI break. The packed type is 64-bit so this reduces the maximum number of 5281ad6265SDimitry Andric /// packed elements from 16 to 12. 53bdd1243dSDimitry Andric /// 54bdd1243dSDimitry Andric /// @note Some members of this enum are an extension. These extensions need 55bdd1243dSDimitry Andric /// special behaviour in visit_format_arg. There they need to be wrapped in a 56bdd1243dSDimitry Andric /// handle to satisfy the user observable behaviour. The internal function 57bdd1243dSDimitry Andric /// __visit_format_arg doesn't do this wrapping. So in the format functions 58bdd1243dSDimitry Andric /// this function is used to avoid unneeded overhead. 595f757f3fSDimitry Andric enum class __arg_t : uint8_t { 60349cc55cSDimitry Andric __none, 61349cc55cSDimitry Andric __boolean, 62349cc55cSDimitry Andric __char_type, 63349cc55cSDimitry Andric __int, 64349cc55cSDimitry Andric __long_long, 65bdd1243dSDimitry Andric __i128, // extension 66349cc55cSDimitry Andric __unsigned, 67349cc55cSDimitry Andric __unsigned_long_long, 68bdd1243dSDimitry Andric __u128, // extension 69349cc55cSDimitry Andric __float, 70349cc55cSDimitry Andric __double, 71349cc55cSDimitry Andric __long_double, 72349cc55cSDimitry Andric __const_char_type_ptr, 73349cc55cSDimitry Andric __string_view, 7404eeddc0SDimitry Andric __ptr, 7504eeddc0SDimitry Andric __handle 76349cc55cSDimitry Andric }; 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric inline constexpr unsigned __packed_arg_t_bits = 5; 7981ad6265SDimitry Andric inline constexpr uint8_t __packed_arg_t_mask = 0x1f; 8081ad6265SDimitry Andric 8181ad6265SDimitry Andric inline constexpr unsigned __packed_types_storage_bits = 64; 8281ad6265SDimitry Andric inline constexpr unsigned __packed_types_max = __packed_types_storage_bits / __packed_arg_t_bits; 8381ad6265SDimitry Andric 84cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool __use_packed_format_arg_store(size_t __size) { 85cb14a3feSDimitry Andric return __size <= __packed_types_max; 86cb14a3feSDimitry Andric } 8781ad6265SDimitry Andric 88cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { 891db9f3b2SDimitry Andric _LIBCPP_ASSERT_INTERNAL(__id <= __packed_types_max, ""); 9081ad6265SDimitry Andric 9181ad6265SDimitry Andric if (__id > 0) 9281ad6265SDimitry Andric __types >>= __id * __packed_arg_t_bits; 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric return static_cast<__format::__arg_t>(__types & __packed_arg_t_mask); 9581ad6265SDimitry Andric } 9681ad6265SDimitry Andric 97349cc55cSDimitry Andric } // namespace __format 98349cc55cSDimitry Andric 99*0fca6ea1SDimitry Andric // This function is not user observable, so it can directly use the non-standard 100bdd1243dSDimitry Andric // types of the "variant". See __arg_t for more details. 101349cc55cSDimitry Andric template <class _Visitor, class _Context> 102cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { 103349cc55cSDimitry Andric switch (__arg.__type_) { 104349cc55cSDimitry Andric case __format::__arg_t::__none: 1055f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_); 106349cc55cSDimitry Andric case __format::__arg_t::__boolean: 1075f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_); 108349cc55cSDimitry Andric case __format::__arg_t::__char_type: 1095f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_); 110349cc55cSDimitry Andric case __format::__arg_t::__int: 1115f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__int_); 112349cc55cSDimitry Andric case __format::__arg_t::__long_long: 1135f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_); 114349cc55cSDimitry Andric case __format::__arg_t::__i128: 1150eae32dcSDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 1165f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__i128_); 1170eae32dcSDimitry Andric # else 11881ad6265SDimitry Andric __libcpp_unreachable(); 119349cc55cSDimitry Andric # endif 120349cc55cSDimitry Andric case __format::__arg_t::__unsigned: 1215f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_); 122349cc55cSDimitry Andric case __format::__arg_t::__unsigned_long_long: 1235f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); 124349cc55cSDimitry Andric case __format::__arg_t::__u128: 1250eae32dcSDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 1265f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__u128_); 1270eae32dcSDimitry Andric # else 12881ad6265SDimitry Andric __libcpp_unreachable(); 129349cc55cSDimitry Andric # endif 130349cc55cSDimitry Andric case __format::__arg_t::__float: 1315f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__float_); 132349cc55cSDimitry Andric case __format::__arg_t::__double: 1335f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__double_); 134349cc55cSDimitry Andric case __format::__arg_t::__long_double: 1355f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_); 136349cc55cSDimitry Andric case __format::__arg_t::__const_char_type_ptr: 1375f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_); 138349cc55cSDimitry Andric case __format::__arg_t::__string_view: 1395f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_); 140349cc55cSDimitry Andric case __format::__arg_t::__ptr: 1415f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_); 14204eeddc0SDimitry Andric case __format::__arg_t::__handle: 143cb14a3feSDimitry Andric return std::invoke( 144cb14a3feSDimitry Andric std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_}); 145349cc55cSDimitry Andric } 14681ad6265SDimitry Andric 14781ad6265SDimitry Andric __libcpp_unreachable(); 148349cc55cSDimitry Andric } 149349cc55cSDimitry Andric 150*0fca6ea1SDimitry Andric # if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) 151*0fca6ea1SDimitry Andric 152*0fca6ea1SDimitry Andric template <class _Rp, class _Visitor, class _Context> 153*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { 154*0fca6ea1SDimitry Andric switch (__arg.__type_) { 155*0fca6ea1SDimitry Andric case __format::__arg_t::__none: 156*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_); 157*0fca6ea1SDimitry Andric case __format::__arg_t::__boolean: 158*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_); 159*0fca6ea1SDimitry Andric case __format::__arg_t::__char_type: 160*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_); 161*0fca6ea1SDimitry Andric case __format::__arg_t::__int: 162*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__int_); 163*0fca6ea1SDimitry Andric case __format::__arg_t::__long_long: 164*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_); 165*0fca6ea1SDimitry Andric case __format::__arg_t::__i128: 166*0fca6ea1SDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 167*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__i128_); 168*0fca6ea1SDimitry Andric # else 169*0fca6ea1SDimitry Andric __libcpp_unreachable(); 170*0fca6ea1SDimitry Andric # endif 171*0fca6ea1SDimitry Andric case __format::__arg_t::__unsigned: 172*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_); 173*0fca6ea1SDimitry Andric case __format::__arg_t::__unsigned_long_long: 174*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); 175*0fca6ea1SDimitry Andric case __format::__arg_t::__u128: 176*0fca6ea1SDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 177*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__u128_); 178*0fca6ea1SDimitry Andric # else 179*0fca6ea1SDimitry Andric __libcpp_unreachable(); 180*0fca6ea1SDimitry Andric # endif 181*0fca6ea1SDimitry Andric case __format::__arg_t::__float: 182*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__float_); 183*0fca6ea1SDimitry Andric case __format::__arg_t::__double: 184*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__double_); 185*0fca6ea1SDimitry Andric case __format::__arg_t::__long_double: 186*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_); 187*0fca6ea1SDimitry Andric case __format::__arg_t::__const_char_type_ptr: 188*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_); 189*0fca6ea1SDimitry Andric case __format::__arg_t::__string_view: 190*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_); 191*0fca6ea1SDimitry Andric case __format::__arg_t::__ptr: 192*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_); 193*0fca6ea1SDimitry Andric case __format::__arg_t::__handle: 194*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>( 195*0fca6ea1SDimitry Andric std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_}); 196*0fca6ea1SDimitry Andric } 197*0fca6ea1SDimitry Andric 198*0fca6ea1SDimitry Andric __libcpp_unreachable(); 199*0fca6ea1SDimitry Andric } 200*0fca6ea1SDimitry Andric 201*0fca6ea1SDimitry Andric # endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) 202*0fca6ea1SDimitry Andric 20381ad6265SDimitry Andric /// Contains the values used in basic_format_arg. 20481ad6265SDimitry Andric /// 20581ad6265SDimitry Andric /// This is a separate type so it's possible to store the values and types in 20681ad6265SDimitry Andric /// separate arrays. 20781ad6265SDimitry Andric template <class _Context> 20881ad6265SDimitry Andric class __basic_format_arg_value { 20981ad6265SDimitry Andric using _CharT = typename _Context::char_type; 21081ad6265SDimitry Andric 21181ad6265SDimitry Andric public: 21281ad6265SDimitry Andric /// Contains the implementation for basic_format_arg::handle. 21381ad6265SDimitry Andric struct __handle { 21481ad6265SDimitry Andric template <class _Tp> 21506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp& __v) noexcept 2165f757f3fSDimitry Andric : __ptr_(std::addressof(__v)), 21781ad6265SDimitry Andric __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) { 21806c3fb27SDimitry Andric using _Dp = remove_const_t<_Tp>; 21906c3fb27SDimitry Andric using _Qp = conditional_t<__formattable_with<const _Dp, _Context>, const _Dp, _Dp>; 22006c3fb27SDimitry Andric static_assert(__formattable_with<_Qp, _Context>, "Mandated by [format.arg]/10"); 221753f127fSDimitry Andric 22206c3fb27SDimitry Andric typename _Context::template formatter_type<_Dp> __f; 22381ad6265SDimitry Andric __parse_ctx.advance_to(__f.parse(__parse_ctx)); 224753f127fSDimitry Andric __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast<const _Dp*>(__ptr)), __ctx)); 22581ad6265SDimitry Andric }) {} 22681ad6265SDimitry Andric 22781ad6265SDimitry Andric const void* __ptr_; 22881ad6265SDimitry Andric void (*__format_)(basic_format_parse_context<_CharT>&, _Context&, const void*); 22981ad6265SDimitry Andric }; 23081ad6265SDimitry Andric 23181ad6265SDimitry Andric union { 23281ad6265SDimitry Andric monostate __monostate_; 23381ad6265SDimitry Andric bool __boolean_; 23481ad6265SDimitry Andric _CharT __char_type_; 23581ad6265SDimitry Andric int __int_; 23681ad6265SDimitry Andric unsigned __unsigned_; 23781ad6265SDimitry Andric long long __long_long_; 23881ad6265SDimitry Andric unsigned long long __unsigned_long_long_; 23981ad6265SDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 24081ad6265SDimitry Andric __int128_t __i128_; 24181ad6265SDimitry Andric __uint128_t __u128_; 24281ad6265SDimitry Andric # endif 24381ad6265SDimitry Andric float __float_; 24481ad6265SDimitry Andric double __double_; 24581ad6265SDimitry Andric long double __long_double_; 24681ad6265SDimitry Andric const _CharT* __const_char_type_ptr_; 24781ad6265SDimitry Andric basic_string_view<_CharT> __string_view_; 24881ad6265SDimitry Andric const void* __ptr_; 24981ad6265SDimitry Andric __handle __handle_; 25081ad6265SDimitry Andric }; 25181ad6265SDimitry Andric 25281ad6265SDimitry Andric // These constructors contain the exact storage type used. If adjustments are 25381ad6265SDimitry Andric // required, these will be done in __create_format_arg. 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value() noexcept : __monostate_() {} 25681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(bool __value) noexcept : __boolean_(__value) {} 25781ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(_CharT __value) noexcept : __char_type_(__value) {} 25881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(int __value) noexcept : __int_(__value) {} 25981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned __value) noexcept : __unsigned_(__value) {} 26081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long long __value) noexcept : __long_long_(__value) {} 26181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned long long __value) noexcept 26281ad6265SDimitry Andric : __unsigned_long_long_(__value) {} 26381ad6265SDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 26481ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__int128_t __value) noexcept : __i128_(__value) {} 26581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__uint128_t __value) noexcept : __u128_(__value) {} 26681ad6265SDimitry Andric # endif 26781ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(float __value) noexcept : __float_(__value) {} 26881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(double __value) noexcept : __double_(__value) {} 26981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long double __value) noexcept : __long_double_(__value) {} 27081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const _CharT* __value) noexcept : __const_char_type_ptr_(__value) {} 27181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept 27281ad6265SDimitry Andric : __string_view_(__value) {} 27381ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {} 27406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle&& __value) noexcept : __handle_(std::move(__value)) {} 27581ad6265SDimitry Andric }; 27681ad6265SDimitry Andric 277349cc55cSDimitry Andric template <class _Context> 27806c3fb27SDimitry Andric class _LIBCPP_TEMPLATE_VIS basic_format_arg { 279349cc55cSDimitry Andric public: 28004eeddc0SDimitry Andric class _LIBCPP_TEMPLATE_VIS handle; 281349cc55cSDimitry Andric 282cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept : __type_{__format::__arg_t::__none} {} 283349cc55cSDimitry Andric 284cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __type_ != __format::__arg_t::__none; } 285349cc55cSDimitry Andric 286*0fca6ea1SDimitry Andric # if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) 287*0fca6ea1SDimitry Andric 288*0fca6ea1SDimitry Andric // This function is user facing, so it must wrap the non-standard types of 289*0fca6ea1SDimitry Andric // the "variant" in a handle to stay conforming. See __arg_t for more details. 290*0fca6ea1SDimitry Andric template <class _Visitor> 291*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI decltype(auto) visit(this basic_format_arg __arg, _Visitor&& __vis) { 292*0fca6ea1SDimitry Andric switch (__arg.__type_) { 293*0fca6ea1SDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 294*0fca6ea1SDimitry Andric case __format::__arg_t::__i128: { 295*0fca6ea1SDimitry Andric typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; 296*0fca6ea1SDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 297*0fca6ea1SDimitry Andric } 298*0fca6ea1SDimitry Andric 299*0fca6ea1SDimitry Andric case __format::__arg_t::__u128: { 300*0fca6ea1SDimitry Andric typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; 301*0fca6ea1SDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 302*0fca6ea1SDimitry Andric } 303*0fca6ea1SDimitry Andric # endif 304*0fca6ea1SDimitry Andric default: 305*0fca6ea1SDimitry Andric return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg); 306*0fca6ea1SDimitry Andric } 307*0fca6ea1SDimitry Andric } 308*0fca6ea1SDimitry Andric 309*0fca6ea1SDimitry Andric // This function is user facing, so it must wrap the non-standard types of 310*0fca6ea1SDimitry Andric // the "variant" in a handle to stay conforming. See __arg_t for more details. 311*0fca6ea1SDimitry Andric template <class _Rp, class _Visitor> 312*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _Rp visit(this basic_format_arg __arg, _Visitor&& __vis) { 313*0fca6ea1SDimitry Andric switch (__arg.__type_) { 314*0fca6ea1SDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 315*0fca6ea1SDimitry Andric case __format::__arg_t::__i128: { 316*0fca6ea1SDimitry Andric typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; 317*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 318*0fca6ea1SDimitry Andric } 319*0fca6ea1SDimitry Andric 320*0fca6ea1SDimitry Andric case __format::__arg_t::__u128: { 321*0fca6ea1SDimitry Andric typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; 322*0fca6ea1SDimitry Andric return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 323*0fca6ea1SDimitry Andric } 324*0fca6ea1SDimitry Andric # endif 325*0fca6ea1SDimitry Andric default: 326*0fca6ea1SDimitry Andric return std::__visit_format_arg<_Rp>(std::forward<_Visitor>(__vis), __arg); 327*0fca6ea1SDimitry Andric } 328*0fca6ea1SDimitry Andric } 329*0fca6ea1SDimitry Andric 330*0fca6ea1SDimitry Andric # endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) 331*0fca6ea1SDimitry Andric 332349cc55cSDimitry Andric private: 333349cc55cSDimitry Andric using char_type = typename _Context::char_type; 334349cc55cSDimitry Andric 335349cc55cSDimitry Andric // TODO FMT Implement constrain [format.arg]/4 336349cc55cSDimitry Andric // Constraints: The template specialization 337349cc55cSDimitry Andric // typename Context::template formatter_type<T> 338349cc55cSDimitry Andric // meets the Formatter requirements ([formatter.requirements]). The extent 339349cc55cSDimitry Andric // to which an implementation determines that the specialization meets the 340349cc55cSDimitry Andric // Formatter requirements is unspecified, except that as a minimum the 341349cc55cSDimitry Andric // expression 342349cc55cSDimitry Andric // typename Context::template formatter_type<T>() 343349cc55cSDimitry Andric // .format(declval<const T&>(), declval<Context&>()) 344349cc55cSDimitry Andric // shall be well-formed when treated as an unevaluated operand. 345349cc55cSDimitry Andric 34681ad6265SDimitry Andric public: 34781ad6265SDimitry Andric __basic_format_arg_value<_Context> __value_; 348349cc55cSDimitry Andric __format::__arg_t __type_; 349349cc55cSDimitry Andric 35081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type, 35181ad6265SDimitry Andric __basic_format_arg_value<_Context> __value) noexcept 35281ad6265SDimitry Andric : __value_(__value), __type_(__type) {} 35304eeddc0SDimitry Andric }; 35404eeddc0SDimitry Andric 35504eeddc0SDimitry Andric template <class _Context> 35604eeddc0SDimitry Andric class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle { 35704eeddc0SDimitry Andric public: 358cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void format(basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx) const { 35981ad6265SDimitry Andric __handle_.__format_(__parse_ctx, __ctx, __handle_.__ptr_); 36004eeddc0SDimitry Andric } 36104eeddc0SDimitry Andric 362753f127fSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit handle(typename __basic_format_arg_value<_Context>::__handle& __handle) noexcept 36381ad6265SDimitry Andric : __handle_(__handle) {} 36481ad6265SDimitry Andric 36504eeddc0SDimitry Andric private: 366753f127fSDimitry Andric typename __basic_format_arg_value<_Context>::__handle& __handle_; 367349cc55cSDimitry Andric }; 368349cc55cSDimitry Andric 369bdd1243dSDimitry Andric // This function is user facing, so it must wrap the non-standard types of 370bdd1243dSDimitry Andric // the "variant" in a handle to stay conforming. See __arg_t for more details. 371bdd1243dSDimitry Andric template <class _Visitor, class _Context> 372*0fca6ea1SDimitry Andric # if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) 373*0fca6ea1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX26 374*0fca6ea1SDimitry Andric # endif 375*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI decltype(auto) 376*0fca6ea1SDimitry Andric visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { 377bdd1243dSDimitry Andric switch (__arg.__type_) { 378bdd1243dSDimitry Andric # ifndef _LIBCPP_HAS_NO_INT128 379bdd1243dSDimitry Andric case __format::__arg_t::__i128: { 380bdd1243dSDimitry Andric typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; 3815f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 382bdd1243dSDimitry Andric } 383bdd1243dSDimitry Andric 384bdd1243dSDimitry Andric case __format::__arg_t::__u128: { 385bdd1243dSDimitry Andric typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; 3865f757f3fSDimitry Andric return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 387bdd1243dSDimitry Andric } 388*0fca6ea1SDimitry Andric # endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) 389bdd1243dSDimitry Andric default: 3905f757f3fSDimitry Andric return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg); 391bdd1243dSDimitry Andric } 392bdd1243dSDimitry Andric } 393bdd1243dSDimitry Andric 39406c3fb27SDimitry Andric #endif //_LIBCPP_STD_VER >= 20 395349cc55cSDimitry Andric 396349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD 397349cc55cSDimitry Andric 398b3edf446SDimitry Andric _LIBCPP_POP_MACROS 399b3edf446SDimitry Andric 400349cc55cSDimitry Andric #endif // _LIBCPP___FORMAT_FORMAT_ARG_H 401