xref: /llvm-project/libcxx/include/__format/format_arg.h (revision 6f684816e25d8b4e5fb2cbc7d0560d608a8bd938)
10922ce56SMark de Wever // -*- C++ -*-
20922ce56SMark de Wever //===----------------------------------------------------------------------===//
30922ce56SMark de Wever //
40922ce56SMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50922ce56SMark de Wever // See https://llvm.org/LICENSE.txt for license information.
60922ce56SMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70922ce56SMark de Wever //
80922ce56SMark de Wever //===----------------------------------------------------------------------===//
90922ce56SMark de Wever 
100922ce56SMark de Wever #ifndef _LIBCPP___FORMAT_FORMAT_ARG_H
110922ce56SMark de Wever #define _LIBCPP___FORMAT_FORMAT_ARG_H
120922ce56SMark de Wever 
13f87aa19bSLouis Dionne #include <__assert>
1416379211SMark de Wever #include <__concepts/arithmetic.h>
150922ce56SMark de Wever #include <__config>
16e99c4906SNikolas Klauser #include <__cstddef/size_t.h>
1748abcf11SMark de Wever #include <__format/concepts.h>
18ade6d0d8SMark de Wever #include <__format/format_parse_context.h>
1934f73804SNikolas Klauser #include <__functional/invoke.h>
2008766681SNikolas Klauser #include <__fwd/format.h>
21ade6d0d8SMark de Wever #include <__memory/addressof.h>
2279702f7fSIan Anderson #include <__type_traits/conditional.h>
23472b612cSNikolas Klauser #include <__type_traits/remove_const.h>
2434f73804SNikolas Klauser #include <__utility/forward.h>
25285e1e2aSMark de Wever #include <__utility/move.h>
262a8f9a5eSNikolas Klauser #include <__utility/unreachable.h>
270922ce56SMark de Wever #include <__variant/monostate.h>
28285e1e2aSMark de Wever #include <cstdint>
290922ce56SMark de Wever #include <string_view>
300922ce56SMark de Wever 
310922ce56SMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
320922ce56SMark de Wever #  pragma GCC system_header
330922ce56SMark de Wever #endif
340922ce56SMark de Wever 
357b462251SLouis Dionne _LIBCPP_PUSH_MACROS
367b462251SLouis Dionne #include <__undef_macros>
377b462251SLouis Dionne 
380922ce56SMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD
390922ce56SMark de Wever 
404f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20
410922ce56SMark de Wever 
420922ce56SMark de Wever namespace __format {
43dfb20d4dSMark de Wever /// The type stored in @ref basic_format_arg.
44dfb20d4dSMark de Wever ///
45dfb20d4dSMark de Wever /// @note The 128-bit types are unconditionally in the list to avoid the values
46dfb20d4dSMark de Wever /// of the enums to depend on the availability of 128-bit integers.
474d8268fbSMark de Wever ///
484d8268fbSMark de Wever /// @note The value is stored as a 5-bit value in the __packed_arg_t_bits. This
494d8268fbSMark de Wever /// limits the maximum number of elements to 32.
504d8268fbSMark de Wever /// When modifying update the test
514d8268fbSMark de Wever /// test/libcxx/utilities/format/format.arguments/format.arg/arg_t.compile.pass.cpp
524d8268fbSMark de Wever /// It could be packed in 4-bits but that means a new type directly becomes an
534d8268fbSMark de Wever /// ABI break. The packed type is 64-bit so this reduces the maximum number of
544d8268fbSMark de Wever /// packed elements from 16 to 12.
55e948cab0SMark de Wever ///
56e948cab0SMark de Wever /// @note Some members of this enum are an extension. These extensions need
57e948cab0SMark de Wever /// special behaviour in visit_format_arg. There they need to be wrapped in a
58e948cab0SMark de Wever /// handle to satisfy the user observable behaviour. The internal function
59e948cab0SMark de Wever /// __visit_format_arg doesn't do this wrapping. So in the format functions
60e948cab0SMark de Wever /// this function is used to avoid unneeded overhead.
613583bf3aSNikolas Klauser enum class __arg_t : uint8_t {
620922ce56SMark de Wever   __none,
6367794e78SMark de Wever   __boolean,
640922ce56SMark de Wever   __char_type,
650922ce56SMark de Wever   __int,
660922ce56SMark de Wever   __long_long,
67e948cab0SMark de Wever   __i128, // extension
680922ce56SMark de Wever   __unsigned,
690922ce56SMark de Wever   __unsigned_long_long,
70e948cab0SMark de Wever   __u128, // extension
710922ce56SMark de Wever   __float,
720922ce56SMark de Wever   __double,
730922ce56SMark de Wever   __long_double,
740922ce56SMark de Wever   __const_char_type_ptr,
750922ce56SMark de Wever   __string_view,
76ade6d0d8SMark de Wever   __ptr,
77ade6d0d8SMark de Wever   __handle
780922ce56SMark de Wever };
794d8268fbSMark de Wever 
804d8268fbSMark de Wever inline constexpr unsigned __packed_arg_t_bits = 5;
814d8268fbSMark de Wever inline constexpr uint8_t __packed_arg_t_mask  = 0x1f;
824d8268fbSMark de Wever 
834d8268fbSMark de Wever inline constexpr unsigned __packed_types_storage_bits = 64;
844d8268fbSMark de Wever inline constexpr unsigned __packed_types_max          = __packed_types_storage_bits / __packed_arg_t_bits;
854d8268fbSMark de Wever 
869783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr bool __use_packed_format_arg_store(size_t __size) {
879783f28cSLouis Dionne   return __size <= __packed_types_max;
889783f28cSLouis Dionne }
894d8268fbSMark de Wever 
909783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) {
914f215fddSKonstantin Varlamov   _LIBCPP_ASSERT_INTERNAL(__id <= __packed_types_max, "");
924d8268fbSMark de Wever 
934d8268fbSMark de Wever   if (__id > 0)
944d8268fbSMark de Wever     __types >>= __id * __packed_arg_t_bits;
954d8268fbSMark de Wever 
964d8268fbSMark de Wever   return static_cast<__format::__arg_t>(__types & __packed_arg_t_mask);
974d8268fbSMark de Wever }
984d8268fbSMark de Wever 
990922ce56SMark de Wever } // namespace __format
1000922ce56SMark de Wever 
10127e67cdbSHristo Hristov // This function is not user observable, so it can directly use the non-standard
102e948cab0SMark de Wever // types of the "variant". See __arg_t for more details.
1030922ce56SMark de Wever template <class _Visitor, class _Context>
1049783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
1050922ce56SMark de Wever   switch (__arg.__type_) {
1060922ce56SMark de Wever   case __format::__arg_t::__none:
10777a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_);
10867794e78SMark de Wever   case __format::__arg_t::__boolean:
10977a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_);
1100922ce56SMark de Wever   case __format::__arg_t::__char_type:
11177a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_);
1120922ce56SMark de Wever   case __format::__arg_t::__int:
11377a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__int_);
1140922ce56SMark de Wever   case __format::__arg_t::__long_long:
11577a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_);
1160922ce56SMark de Wever   case __format::__arg_t::__i128:
117ba87515fSNikolas Klauser #  if _LIBCPP_HAS_INT128
11877a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__i128_);
119dfb20d4dSMark de Wever #  else
1202a8f9a5eSNikolas Klauser     __libcpp_unreachable();
1210922ce56SMark de Wever #  endif
1220922ce56SMark de Wever   case __format::__arg_t::__unsigned:
12377a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_);
1240922ce56SMark de Wever   case __format::__arg_t::__unsigned_long_long:
12577a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_);
1260922ce56SMark de Wever   case __format::__arg_t::__u128:
127ba87515fSNikolas Klauser #  if _LIBCPP_HAS_INT128
12877a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__u128_);
129dfb20d4dSMark de Wever #  else
1302a8f9a5eSNikolas Klauser     __libcpp_unreachable();
1310922ce56SMark de Wever #  endif
1320922ce56SMark de Wever   case __format::__arg_t::__float:
13377a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__float_);
1340922ce56SMark de Wever   case __format::__arg_t::__double:
13577a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__double_);
1360922ce56SMark de Wever   case __format::__arg_t::__long_double:
13777a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_);
1380922ce56SMark de Wever   case __format::__arg_t::__const_char_type_ptr:
13977a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_);
1400922ce56SMark de Wever   case __format::__arg_t::__string_view:
14177a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_);
1420922ce56SMark de Wever   case __format::__arg_t::__ptr:
14377a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_);
144ade6d0d8SMark de Wever   case __format::__arg_t::__handle:
1459783f28cSLouis Dionne     return std::invoke(
1469783f28cSLouis Dionne         std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_});
1470922ce56SMark de Wever   }
1484d8268fbSMark de Wever 
1492a8f9a5eSNikolas Klauser   __libcpp_unreachable();
1500922ce56SMark de Wever }
1510922ce56SMark de Wever 
152ba87515fSNikolas Klauser #  if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
15327e67cdbSHristo Hristov 
15427e67cdbSHristo Hristov template <class _Rp, class _Visitor, class _Context>
15527e67cdbSHristo Hristov _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
15627e67cdbSHristo Hristov   switch (__arg.__type_) {
15727e67cdbSHristo Hristov   case __format::__arg_t::__none:
15827e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_);
15927e67cdbSHristo Hristov   case __format::__arg_t::__boolean:
16027e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_);
16127e67cdbSHristo Hristov   case __format::__arg_t::__char_type:
16227e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_);
16327e67cdbSHristo Hristov   case __format::__arg_t::__int:
16427e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__int_);
16527e67cdbSHristo Hristov   case __format::__arg_t::__long_long:
16627e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_);
16727e67cdbSHristo Hristov   case __format::__arg_t::__i128:
168ba87515fSNikolas Klauser #    if _LIBCPP_HAS_INT128
16927e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__i128_);
17027e67cdbSHristo Hristov #    else
17127e67cdbSHristo Hristov     __libcpp_unreachable();
17227e67cdbSHristo Hristov #    endif
17327e67cdbSHristo Hristov   case __format::__arg_t::__unsigned:
17427e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_);
17527e67cdbSHristo Hristov   case __format::__arg_t::__unsigned_long_long:
17627e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_);
17727e67cdbSHristo Hristov   case __format::__arg_t::__u128:
178ba87515fSNikolas Klauser #    if _LIBCPP_HAS_INT128
17927e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__u128_);
18027e67cdbSHristo Hristov #    else
18127e67cdbSHristo Hristov     __libcpp_unreachable();
18227e67cdbSHristo Hristov #    endif
18327e67cdbSHristo Hristov   case __format::__arg_t::__float:
18427e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__float_);
18527e67cdbSHristo Hristov   case __format::__arg_t::__double:
18627e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__double_);
18727e67cdbSHristo Hristov   case __format::__arg_t::__long_double:
18827e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_);
18927e67cdbSHristo Hristov   case __format::__arg_t::__const_char_type_ptr:
19027e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_);
19127e67cdbSHristo Hristov   case __format::__arg_t::__string_view:
19227e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_);
19327e67cdbSHristo Hristov   case __format::__arg_t::__ptr:
19427e67cdbSHristo Hristov     return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_);
19527e67cdbSHristo Hristov   case __format::__arg_t::__handle:
19627e67cdbSHristo Hristov     return std::invoke_r<_Rp>(
19727e67cdbSHristo Hristov         std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_});
19827e67cdbSHristo Hristov   }
19927e67cdbSHristo Hristov 
20027e67cdbSHristo Hristov   __libcpp_unreachable();
20127e67cdbSHristo Hristov }
20227e67cdbSHristo Hristov 
203ba87515fSNikolas Klauser #  endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
20427e67cdbSHristo Hristov 
2054d8268fbSMark de Wever /// Contains the values used in basic_format_arg.
2064d8268fbSMark de Wever ///
2074d8268fbSMark de Wever /// This is a separate type so it's possible to store the values and types in
2084d8268fbSMark de Wever /// separate arrays.
2094d8268fbSMark de Wever template <class _Context>
2104d8268fbSMark de Wever class __basic_format_arg_value {
211f6958523SNikolas Klauser   using _CharT _LIBCPP_NODEBUG = typename _Context::char_type;
2124d8268fbSMark de Wever 
2134d8268fbSMark de Wever public:
2144d8268fbSMark de Wever   /// Contains the implementation for basic_format_arg::handle.
2154d8268fbSMark de Wever   struct __handle {
2164d8268fbSMark de Wever     template <class _Tp>
21748abcf11SMark de Wever     _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp& __v) noexcept
21877a00c0dSLouis Dionne         : __ptr_(std::addressof(__v)),
2194d8268fbSMark de Wever           __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) {
22048abcf11SMark de Wever             using _Dp = remove_const_t<_Tp>;
22148abcf11SMark de Wever             using _Qp = conditional_t<__formattable_with<const _Dp, _Context>, const _Dp, _Dp>;
22248abcf11SMark de Wever             static_assert(__formattable_with<_Qp, _Context>, "Mandated by [format.arg]/10");
223606e2808SMark de Wever 
22448abcf11SMark de Wever             typename _Context::template formatter_type<_Dp> __f;
2254d8268fbSMark de Wever             __parse_ctx.advance_to(__f.parse(__parse_ctx));
226606e2808SMark de Wever             __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast<const _Dp*>(__ptr)), __ctx));
2274d8268fbSMark de Wever           }) {}
2284d8268fbSMark de Wever 
2294d8268fbSMark de Wever     const void* __ptr_;
2304d8268fbSMark de Wever     void (*__format_)(basic_format_parse_context<_CharT>&, _Context&, const void*);
2314d8268fbSMark de Wever   };
2324d8268fbSMark de Wever 
2334d8268fbSMark de Wever   union {
2344d8268fbSMark de Wever     monostate __monostate_;
2354d8268fbSMark de Wever     bool __boolean_;
2364d8268fbSMark de Wever     _CharT __char_type_;
2374d8268fbSMark de Wever     int __int_;
2384d8268fbSMark de Wever     unsigned __unsigned_;
2394d8268fbSMark de Wever     long long __long_long_;
2404d8268fbSMark de Wever     unsigned long long __unsigned_long_long_;
241ba87515fSNikolas Klauser #  if _LIBCPP_HAS_INT128
2424d8268fbSMark de Wever     __int128_t __i128_;
2434d8268fbSMark de Wever     __uint128_t __u128_;
2444d8268fbSMark de Wever #  endif
2454d8268fbSMark de Wever     float __float_;
2464d8268fbSMark de Wever     double __double_;
2474d8268fbSMark de Wever     long double __long_double_;
2484d8268fbSMark de Wever     const _CharT* __const_char_type_ptr_;
2494d8268fbSMark de Wever     basic_string_view<_CharT> __string_view_;
2504d8268fbSMark de Wever     const void* __ptr_;
2514d8268fbSMark de Wever     __handle __handle_;
2524d8268fbSMark de Wever   };
2534d8268fbSMark de Wever 
2544d8268fbSMark de Wever   // These constructors contain the exact storage type used. If adjustments are
2554d8268fbSMark de Wever   // required, these will be done in __create_format_arg.
2564d8268fbSMark de Wever 
2574d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value() noexcept : __monostate_() {}
2584d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(bool __value) noexcept : __boolean_(__value) {}
2594d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(_CharT __value) noexcept : __char_type_(__value) {}
2604d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(int __value) noexcept : __int_(__value) {}
2614d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned __value) noexcept : __unsigned_(__value) {}
2624d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long long __value) noexcept : __long_long_(__value) {}
2634d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned long long __value) noexcept
2644d8268fbSMark de Wever       : __unsigned_long_long_(__value) {}
265ba87515fSNikolas Klauser #  if _LIBCPP_HAS_INT128
2664d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__int128_t __value) noexcept : __i128_(__value) {}
2674d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__uint128_t __value) noexcept : __u128_(__value) {}
2684d8268fbSMark de Wever #  endif
2694d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(float __value) noexcept : __float_(__value) {}
2704d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(double __value) noexcept : __double_(__value) {}
2714d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long double __value) noexcept : __long_double_(__value) {}
2724d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const _CharT* __value) noexcept : __const_char_type_ptr_(__value) {}
2734d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept
2744d8268fbSMark de Wever       : __string_view_(__value) {}
2754d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {}
27648abcf11SMark de Wever   _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle&& __value) noexcept : __handle_(std::move(__value)) {}
2774d8268fbSMark de Wever };
2784d8268fbSMark de Wever 
2790922ce56SMark de Wever template <class _Context>
280*6f684816SNikolas Klauser class _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS basic_format_arg {
2810922ce56SMark de Wever public:
282ade6d0d8SMark de Wever   class _LIBCPP_TEMPLATE_VIS handle;
2830922ce56SMark de Wever 
2849783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept : __type_{__format::__arg_t::__none} {}
2850922ce56SMark de Wever 
2869783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __type_ != __format::__arg_t::__none; }
2870922ce56SMark de Wever 
288ba87515fSNikolas Klauser #  if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
28927e67cdbSHristo Hristov 
29027e67cdbSHristo Hristov   // This function is user facing, so it must wrap the non-standard types of
29127e67cdbSHristo Hristov   // the "variant" in a handle to stay conforming. See __arg_t for more details.
29227e67cdbSHristo Hristov   template <class _Visitor>
29327e67cdbSHristo Hristov   _LIBCPP_HIDE_FROM_ABI decltype(auto) visit(this basic_format_arg __arg, _Visitor&& __vis) {
29427e67cdbSHristo Hristov     switch (__arg.__type_) {
295ba87515fSNikolas Klauser #    if _LIBCPP_HAS_INT128
29627e67cdbSHristo Hristov     case __format::__arg_t::__i128: {
29727e67cdbSHristo Hristov       typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_};
29827e67cdbSHristo Hristov       return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
29927e67cdbSHristo Hristov     }
30027e67cdbSHristo Hristov 
30127e67cdbSHristo Hristov     case __format::__arg_t::__u128: {
30227e67cdbSHristo Hristov       typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
30327e67cdbSHristo Hristov       return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
30427e67cdbSHristo Hristov     }
30527e67cdbSHristo Hristov #    endif
30627e67cdbSHristo Hristov     default:
30727e67cdbSHristo Hristov       return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg);
30827e67cdbSHristo Hristov     }
30927e67cdbSHristo Hristov   }
31027e67cdbSHristo Hristov 
31127e67cdbSHristo Hristov   // This function is user facing, so it must wrap the non-standard types of
31227e67cdbSHristo Hristov   // the "variant" in a handle to stay conforming. See __arg_t for more details.
31327e67cdbSHristo Hristov   template <class _Rp, class _Visitor>
31427e67cdbSHristo Hristov   _LIBCPP_HIDE_FROM_ABI _Rp visit(this basic_format_arg __arg, _Visitor&& __vis) {
31527e67cdbSHristo Hristov     switch (__arg.__type_) {
316ba87515fSNikolas Klauser #    if _LIBCPP_HAS_INT128
31727e67cdbSHristo Hristov     case __format::__arg_t::__i128: {
31827e67cdbSHristo Hristov       typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_};
31927e67cdbSHristo Hristov       return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
32027e67cdbSHristo Hristov     }
32127e67cdbSHristo Hristov 
32227e67cdbSHristo Hristov     case __format::__arg_t::__u128: {
32327e67cdbSHristo Hristov       typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
32427e67cdbSHristo Hristov       return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
32527e67cdbSHristo Hristov     }
32627e67cdbSHristo Hristov #    endif
32727e67cdbSHristo Hristov     default:
32827e67cdbSHristo Hristov       return std::__visit_format_arg<_Rp>(std::forward<_Visitor>(__vis), __arg);
32927e67cdbSHristo Hristov     }
33027e67cdbSHristo Hristov   }
33127e67cdbSHristo Hristov 
332ba87515fSNikolas Klauser #  endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
33327e67cdbSHristo Hristov 
3340922ce56SMark de Wever private:
3350922ce56SMark de Wever   using char_type = typename _Context::char_type;
3360922ce56SMark de Wever 
3370922ce56SMark de Wever   // TODO FMT Implement constrain [format.arg]/4
3380922ce56SMark de Wever   // Constraints: The template specialization
3390922ce56SMark de Wever   //   typename Context::template formatter_type<T>
3400922ce56SMark de Wever   // meets the Formatter requirements ([formatter.requirements]).  The extent
3410922ce56SMark de Wever   // to which an implementation determines that the specialization meets the
3420922ce56SMark de Wever   // Formatter requirements is unspecified, except that as a minimum the
3430922ce56SMark de Wever   // expression
3440922ce56SMark de Wever   //   typename Context::template formatter_type<T>()
3450922ce56SMark de Wever   //    .format(declval<const T&>(), declval<Context&>())
3460922ce56SMark de Wever   // shall be well-formed when treated as an unevaluated operand.
3470922ce56SMark de Wever 
3484d8268fbSMark de Wever public:
3494d8268fbSMark de Wever   __basic_format_arg_value<_Context> __value_;
3500922ce56SMark de Wever   __format::__arg_t __type_;
3510922ce56SMark de Wever 
3524d8268fbSMark de Wever   _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type,
3534d8268fbSMark de Wever                                                   __basic_format_arg_value<_Context> __value) noexcept
3544d8268fbSMark de Wever       : __value_(__value), __type_(__type) {}
355ade6d0d8SMark de Wever };
356ade6d0d8SMark de Wever 
357ade6d0d8SMark de Wever template <class _Context>
358ade6d0d8SMark de Wever class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle {
359ade6d0d8SMark de Wever public:
3609783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void format(basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx) const {
3614d8268fbSMark de Wever     __handle_.__format_(__parse_ctx, __ctx, __handle_.__ptr_);
362ade6d0d8SMark de Wever   }
363ade6d0d8SMark de Wever 
364606e2808SMark de Wever   _LIBCPP_HIDE_FROM_ABI explicit handle(typename __basic_format_arg_value<_Context>::__handle& __handle) noexcept
3654d8268fbSMark de Wever       : __handle_(__handle) {}
366ade6d0d8SMark de Wever 
3674d8268fbSMark de Wever private:
368606e2808SMark de Wever   typename __basic_format_arg_value<_Context>::__handle& __handle_;
3690922ce56SMark de Wever };
3700922ce56SMark de Wever 
371e948cab0SMark de Wever // This function is user facing, so it must wrap the non-standard types of
372e948cab0SMark de Wever // the "variant" in a handle to stay conforming. See __arg_t for more details.
373e948cab0SMark de Wever template <class _Visitor, class _Context>
374ba87515fSNikolas Klauser #  if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
37527e67cdbSHristo Hristov _LIBCPP_DEPRECATED_IN_CXX26
37627e67cdbSHristo Hristov #  endif
37727e67cdbSHristo Hristov     _LIBCPP_HIDE_FROM_ABI decltype(auto)
37827e67cdbSHristo Hristov     visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
379e948cab0SMark de Wever   switch (__arg.__type_) {
380ba87515fSNikolas Klauser #  if _LIBCPP_HAS_INT128
381e948cab0SMark de Wever   case __format::__arg_t::__i128: {
382e948cab0SMark de Wever     typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_};
38377a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
384e948cab0SMark de Wever   }
385e948cab0SMark de Wever 
386e948cab0SMark de Wever   case __format::__arg_t::__u128: {
387e948cab0SMark de Wever     typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
38877a00c0dSLouis Dionne     return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
389e948cab0SMark de Wever   }
390ba87515fSNikolas Klauser #  endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
391e948cab0SMark de Wever   default:
39277a00c0dSLouis Dionne     return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg);
393e948cab0SMark de Wever   }
394e948cab0SMark de Wever }
395e948cab0SMark de Wever 
3964f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20
3970922ce56SMark de Wever 
3980922ce56SMark de Wever _LIBCPP_END_NAMESPACE_STD
3990922ce56SMark de Wever 
4007b462251SLouis Dionne _LIBCPP_POP_MACROS
4017b462251SLouis Dionne 
4020922ce56SMark de Wever #endif // _LIBCPP___FORMAT_FORMAT_ARG_H
403