1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___FORMAT_FORMAT_ARG_H
11#define _LIBCPP___FORMAT_FORMAT_ARG_H
12
13#include <__assert>
14#include <__concepts/arithmetic.h>
15#include <__config>
16#include <__format/concepts.h>
17#include <__format/format_fwd.h>
18#include <__format/format_parse_context.h>
19#include <__functional/invoke.h>
20#include <__memory/addressof.h>
21#include <__type_traits/conditional.h>
22#include <__utility/forward.h>
23#include <__utility/move.h>
24#include <__utility/unreachable.h>
25#include <__variant/monostate.h>
26#include <cstdint>
27#include <string_view>
28
29#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30#  pragma GCC system_header
31#endif
32
33_LIBCPP_PUSH_MACROS
34#include <__undef_macros>
35
36_LIBCPP_BEGIN_NAMESPACE_STD
37
38#if _LIBCPP_STD_VER >= 20
39
40namespace __format {
41/// The type stored in @ref basic_format_arg.
42///
43/// @note The 128-bit types are unconditionally in the list to avoid the values
44/// of the enums to depend on the availability of 128-bit integers.
45///
46/// @note The value is stored as a 5-bit value in the __packed_arg_t_bits. This
47/// limits the maximum number of elements to 32.
48/// When modifying update the test
49/// test/libcxx/utilities/format/format.arguments/format.arg/arg_t.compile.pass.cpp
50/// It could be packed in 4-bits but that means a new type directly becomes an
51/// ABI break. The packed type is 64-bit so this reduces the maximum number of
52/// packed elements from 16 to 12.
53///
54/// @note Some members of this enum are an extension. These extensions need
55/// special behaviour in visit_format_arg. There they need to be wrapped in a
56/// handle to satisfy the user observable behaviour. The internal function
57/// __visit_format_arg doesn't do this wrapping. So in the format functions
58/// this function is used to avoid unneeded overhead.
59enum class __arg_t : uint8_t {
60  __none,
61  __boolean,
62  __char_type,
63  __int,
64  __long_long,
65  __i128, // extension
66  __unsigned,
67  __unsigned_long_long,
68  __u128, // extension
69  __float,
70  __double,
71  __long_double,
72  __const_char_type_ptr,
73  __string_view,
74  __ptr,
75  __handle
76};
77
78inline constexpr unsigned __packed_arg_t_bits = 5;
79inline constexpr uint8_t __packed_arg_t_mask  = 0x1f;
80
81inline constexpr unsigned __packed_types_storage_bits = 64;
82inline constexpr unsigned __packed_types_max          = __packed_types_storage_bits / __packed_arg_t_bits;
83
84_LIBCPP_HIDE_FROM_ABI constexpr bool __use_packed_format_arg_store(size_t __size) {
85  return __size <= __packed_types_max;
86}
87
88_LIBCPP_HIDE_FROM_ABI constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) {
89  _LIBCPP_ASSERT_INTERNAL(__id <= __packed_types_max, "");
90
91  if (__id > 0)
92    __types >>= __id * __packed_arg_t_bits;
93
94  return static_cast<__format::__arg_t>(__types & __packed_arg_t_mask);
95}
96
97} // namespace __format
98
99// This function is not user obervable, so it can directly use the non-standard
100// types of the "variant". See __arg_t for more details.
101template <class _Visitor, class _Context>
102_LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
103  switch (__arg.__type_) {
104  case __format::__arg_t::__none:
105    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_);
106  case __format::__arg_t::__boolean:
107    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_);
108  case __format::__arg_t::__char_type:
109    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_);
110  case __format::__arg_t::__int:
111    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__int_);
112  case __format::__arg_t::__long_long:
113    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_);
114  case __format::__arg_t::__i128:
115#  ifndef _LIBCPP_HAS_NO_INT128
116    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__i128_);
117#  else
118    __libcpp_unreachable();
119#  endif
120  case __format::__arg_t::__unsigned:
121    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_);
122  case __format::__arg_t::__unsigned_long_long:
123    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_);
124  case __format::__arg_t::__u128:
125#  ifndef _LIBCPP_HAS_NO_INT128
126    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__u128_);
127#  else
128    __libcpp_unreachable();
129#  endif
130  case __format::__arg_t::__float:
131    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__float_);
132  case __format::__arg_t::__double:
133    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__double_);
134  case __format::__arg_t::__long_double:
135    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_);
136  case __format::__arg_t::__const_char_type_ptr:
137    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_);
138  case __format::__arg_t::__string_view:
139    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_);
140  case __format::__arg_t::__ptr:
141    return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_);
142  case __format::__arg_t::__handle:
143    return std::invoke(
144        std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_});
145  }
146
147  __libcpp_unreachable();
148}
149
150/// Contains the values used in basic_format_arg.
151///
152/// This is a separate type so it's possible to store the values and types in
153/// separate arrays.
154template <class _Context>
155class __basic_format_arg_value {
156  using _CharT = typename _Context::char_type;
157
158public:
159  /// Contains the implementation for basic_format_arg::handle.
160  struct __handle {
161    template <class _Tp>
162    _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp& __v) noexcept
163        : __ptr_(std::addressof(__v)),
164          __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) {
165            using _Dp = remove_const_t<_Tp>;
166            using _Qp = conditional_t<__formattable_with<const _Dp, _Context>, const _Dp, _Dp>;
167            static_assert(__formattable_with<_Qp, _Context>, "Mandated by [format.arg]/10");
168
169            typename _Context::template formatter_type<_Dp> __f;
170            __parse_ctx.advance_to(__f.parse(__parse_ctx));
171            __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast<const _Dp*>(__ptr)), __ctx));
172          }) {}
173
174    const void* __ptr_;
175    void (*__format_)(basic_format_parse_context<_CharT>&, _Context&, const void*);
176  };
177
178  union {
179    monostate __monostate_;
180    bool __boolean_;
181    _CharT __char_type_;
182    int __int_;
183    unsigned __unsigned_;
184    long long __long_long_;
185    unsigned long long __unsigned_long_long_;
186#  ifndef _LIBCPP_HAS_NO_INT128
187    __int128_t __i128_;
188    __uint128_t __u128_;
189#  endif
190    float __float_;
191    double __double_;
192    long double __long_double_;
193    const _CharT* __const_char_type_ptr_;
194    basic_string_view<_CharT> __string_view_;
195    const void* __ptr_;
196    __handle __handle_;
197  };
198
199  // These constructors contain the exact storage type used. If adjustments are
200  // required, these will be done in __create_format_arg.
201
202  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value() noexcept : __monostate_() {}
203  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(bool __value) noexcept : __boolean_(__value) {}
204  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(_CharT __value) noexcept : __char_type_(__value) {}
205  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(int __value) noexcept : __int_(__value) {}
206  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned __value) noexcept : __unsigned_(__value) {}
207  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long long __value) noexcept : __long_long_(__value) {}
208  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned long long __value) noexcept
209      : __unsigned_long_long_(__value) {}
210#  ifndef _LIBCPP_HAS_NO_INT128
211  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__int128_t __value) noexcept : __i128_(__value) {}
212  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__uint128_t __value) noexcept : __u128_(__value) {}
213#  endif
214  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(float __value) noexcept : __float_(__value) {}
215  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(double __value) noexcept : __double_(__value) {}
216  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long double __value) noexcept : __long_double_(__value) {}
217  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const _CharT* __value) noexcept : __const_char_type_ptr_(__value) {}
218  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept
219      : __string_view_(__value) {}
220  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {}
221  _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle&& __value) noexcept : __handle_(std::move(__value)) {}
222};
223
224template <class _Context>
225class _LIBCPP_TEMPLATE_VIS basic_format_arg {
226public:
227  class _LIBCPP_TEMPLATE_VIS handle;
228
229  _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept : __type_{__format::__arg_t::__none} {}
230
231  _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __type_ != __format::__arg_t::__none; }
232
233private:
234  using char_type = typename _Context::char_type;
235
236  // TODO FMT Implement constrain [format.arg]/4
237  // Constraints: The template specialization
238  //   typename Context::template formatter_type<T>
239  // meets the Formatter requirements ([formatter.requirements]).  The extent
240  // to which an implementation determines that the specialization meets the
241  // Formatter requirements is unspecified, except that as a minimum the
242  // expression
243  //   typename Context::template formatter_type<T>()
244  //    .format(declval<const T&>(), declval<Context&>())
245  // shall be well-formed when treated as an unevaluated operand.
246
247public:
248  __basic_format_arg_value<_Context> __value_;
249  __format::__arg_t __type_;
250
251  _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type,
252                                                  __basic_format_arg_value<_Context> __value) noexcept
253      : __value_(__value), __type_(__type) {}
254};
255
256template <class _Context>
257class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle {
258public:
259  _LIBCPP_HIDE_FROM_ABI void format(basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx) const {
260    __handle_.__format_(__parse_ctx, __ctx, __handle_.__ptr_);
261  }
262
263  _LIBCPP_HIDE_FROM_ABI explicit handle(typename __basic_format_arg_value<_Context>::__handle& __handle) noexcept
264      : __handle_(__handle) {}
265
266private:
267  typename __basic_format_arg_value<_Context>::__handle& __handle_;
268};
269
270// This function is user facing, so it must wrap the non-standard types of
271// the "variant" in a handle to stay conforming. See __arg_t for more details.
272template <class _Visitor, class _Context>
273_LIBCPP_HIDE_FROM_ABI decltype(auto) visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
274  switch (__arg.__type_) {
275#  ifndef _LIBCPP_HAS_NO_INT128
276  case __format::__arg_t::__i128: {
277    typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_};
278    return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
279  }
280
281  case __format::__arg_t::__u128: {
282    typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
283    return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
284  }
285#  endif
286  default:
287    return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg);
288  }
289}
290
291#endif //_LIBCPP_STD_VER >= 20
292
293_LIBCPP_END_NAMESPACE_STD
294
295_LIBCPP_POP_MACROS
296
297#endif // _LIBCPP___FORMAT_FORMAT_ARG_H
298