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/format_error.h> 17 #include <__format/format_fwd.h> 18 #include <__format/format_parse_context.h> 19 #include <__memory/addressof.h> 20 #include <__utility/unreachable.h> 21 #include <__variant/monostate.h> 22 #include <string> 23 #include <string_view> 24 25 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 26 # pragma GCC system_header 27 #endif 28 29 _LIBCPP_BEGIN_NAMESPACE_STD 30 31 #if _LIBCPP_STD_VER > 17 32 33 namespace __format { 34 /// The type stored in @ref basic_format_arg. 35 /// 36 /// @note The 128-bit types are unconditionally in the list to avoid the values 37 /// of the enums to depend on the availability of 128-bit integers. 38 enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t { 39 __none, 40 __boolean, 41 __char_type, 42 __int, 43 __long_long, 44 __i128, 45 __unsigned, 46 __unsigned_long_long, 47 __u128, 48 __float, 49 __double, 50 __long_double, 51 __const_char_type_ptr, 52 __string_view, 53 __ptr, 54 __handle 55 }; 56 } // namespace __format 57 58 template <class _Visitor, class _Context> 59 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) 60 visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { 61 switch (__arg.__type_) { 62 case __format::__arg_t::__none: 63 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), monostate{}); 64 case __format::__arg_t::__boolean: 65 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__boolean); 66 case __format::__arg_t::__char_type: 67 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__char_type); 68 case __format::__arg_t::__int: 69 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__int); 70 case __format::__arg_t::__long_long: 71 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_long); 72 case __format::__arg_t::__i128: 73 #ifndef _LIBCPP_HAS_NO_INT128 74 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__i128); 75 #else 76 __libcpp_unreachable(); 77 #endif 78 case __format::__arg_t::__unsigned: 79 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__unsigned); 80 case __format::__arg_t::__unsigned_long_long: 81 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), 82 __arg.__unsigned_long_long); 83 case __format::__arg_t::__u128: 84 #ifndef _LIBCPP_HAS_NO_INT128 85 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__u128); 86 #else 87 __libcpp_unreachable(); 88 #endif 89 case __format::__arg_t::__float: 90 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__float); 91 case __format::__arg_t::__double: 92 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__double); 93 case __format::__arg_t::__long_double: 94 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_double); 95 case __format::__arg_t::__const_char_type_ptr: 96 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), 97 __arg.__const_char_type_ptr); 98 case __format::__arg_t::__string_view: 99 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__string_view); 100 case __format::__arg_t::__ptr: 101 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__ptr); 102 case __format::__arg_t::__handle: 103 return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__handle); 104 } 105 __libcpp_unreachable(); 106 } 107 108 template <class _Context> 109 class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg { 110 public: 111 class _LIBCPP_TEMPLATE_VIS handle; 112 113 _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept 114 : __type_{__format::__arg_t::__none} {} 115 116 _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { 117 return __type_ != __format::__arg_t::__none; 118 } 119 120 private: 121 using char_type = typename _Context::char_type; 122 123 // TODO FMT Implement constrain [format.arg]/4 124 // Constraints: The template specialization 125 // typename Context::template formatter_type<T> 126 // meets the Formatter requirements ([formatter.requirements]). The extent 127 // to which an implementation determines that the specialization meets the 128 // Formatter requirements is unspecified, except that as a minimum the 129 // expression 130 // typename Context::template formatter_type<T>() 131 // .format(declval<const T&>(), declval<Context&>()) 132 // shall be well-formed when treated as an unevaluated operand. 133 134 template <class _Ctx, class... _Args> 135 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT friend __format_arg_store<_Ctx, _Args...> 136 make_format_args(const _Args&...); 137 138 template <class _Visitor, class _Ctx> 139 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT friend decltype(auto) 140 visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg); 141 142 union { 143 bool __boolean; 144 char_type __char_type; 145 int __int; 146 unsigned __unsigned; 147 long long __long_long; 148 unsigned long long __unsigned_long_long; 149 #ifndef _LIBCPP_HAS_NO_INT128 150 __int128_t __i128; 151 __uint128_t __u128; 152 #endif 153 float __float; 154 double __double; 155 long double __long_double; 156 const char_type* __const_char_type_ptr; 157 basic_string_view<char_type> __string_view; 158 const void* __ptr; 159 handle __handle; 160 }; 161 __format::__arg_t __type_; 162 163 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const bool& __v) noexcept 164 : __boolean(__v), __type_(__format::__arg_t::__boolean) {} 165 166 template <class _Tp> 167 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const _Tp& __v) noexcept 168 requires(same_as<_Tp, char_type> || 169 (same_as<_Tp, char> && same_as<char_type, wchar_t>)) 170 : __char_type(__v), __type_(__format::__arg_t::__char_type) {} 171 172 template <__libcpp_signed_integer _Tp> 173 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const _Tp& __v) noexcept { 174 if constexpr (sizeof(_Tp) <= sizeof(int)) { 175 __int = static_cast<int>(__v); 176 __type_ = __format::__arg_t::__int; 177 } else if constexpr (sizeof(_Tp) <= sizeof(long long)) { 178 __long_long = static_cast<long long>(__v); 179 __type_ = __format::__arg_t::__long_long; 180 } 181 #ifndef _LIBCPP_HAS_NO_INT128 182 else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) { 183 __i128 = __v; 184 __type_ = __format::__arg_t::__i128; 185 } 186 #endif 187 else 188 static_assert(sizeof(_Tp) == 0, "An unsupported signed integer was used"); 189 } 190 191 template <__libcpp_unsigned_integer _Tp> 192 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const _Tp& __v) noexcept { 193 if constexpr (sizeof(_Tp) <= sizeof(unsigned)) { 194 __unsigned = static_cast<unsigned>(__v); 195 __type_ = __format::__arg_t::__unsigned; 196 } else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) { 197 __unsigned_long_long = static_cast<unsigned long long>(__v); 198 __type_ = __format::__arg_t::__unsigned_long_long; 199 } 200 #ifndef _LIBCPP_HAS_NO_INT128 201 else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) { 202 __u128 = __v; 203 __type_ = __format::__arg_t::__u128; 204 } 205 #endif 206 else 207 static_assert(sizeof(_Tp) == 0, 208 "An unsupported unsigned integer was used"); 209 } 210 211 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(float __v) noexcept 212 : __float(__v), __type_(__format::__arg_t::__float) {} 213 214 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(double __v) noexcept 215 : __double(__v), __type_(__format::__arg_t::__double) {} 216 217 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(long double __v) noexcept 218 : __long_double(__v), __type_(__format::__arg_t::__long_double) {} 219 220 // Note not a 'noexcept' function. 221 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const char_type* __s) 222 : __const_char_type_ptr(__s), 223 __type_(__format::__arg_t::__const_char_type_ptr) { 224 _LIBCPP_ASSERT(__s, "Used a nullptr argument to initialize a C-string"); 225 } 226 227 template <class _Traits> 228 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg( 229 basic_string_view<char_type, _Traits> __s) noexcept 230 : __string_view{__s.data(), __s.size()}, 231 __type_(__format::__arg_t::__string_view) {} 232 233 template <class _Traits, class _Allocator> 234 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg( 235 const basic_string<char_type, _Traits, _Allocator>& __s) noexcept 236 : __string_view{__s.data(), __s.size()}, 237 __type_(__format::__arg_t::__string_view) {} 238 239 _LIBCPP_HIDE_FROM_ABI 240 explicit basic_format_arg(nullptr_t) noexcept 241 : __ptr(nullptr), __type_(__format::__arg_t::__ptr) {} 242 243 template <class _Tp> 244 requires is_void_v<_Tp> _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp* __p) noexcept 245 : __ptr(__p), __type_(__format::__arg_t::__ptr) {} 246 247 template <class _Tp> 248 _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const _Tp& __v) noexcept 249 : __handle(__v), __type_(__format::__arg_t::__handle) {} 250 }; 251 252 template <class _Context> 253 class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle { 254 friend class basic_format_arg<_Context>; 255 256 public: 257 _LIBCPP_HIDE_FROM_ABI 258 void format(basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx) const { 259 __format_(__parse_ctx, __ctx, __ptr_); 260 } 261 262 private: 263 const void* __ptr_; 264 void (*__format_)(basic_format_parse_context<char_type>&, _Context&, const void*); 265 266 template <class _Tp> 267 _LIBCPP_HIDE_FROM_ABI explicit handle(const _Tp& __v) noexcept 268 : __ptr_(_VSTD::addressof(__v)), 269 __format_([](basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx, const void* __ptr) { 270 typename _Context::template formatter_type<_Tp> __f; 271 __parse_ctx.advance_to(__f.parse(__parse_ctx)); 272 __ctx.advance_to(__f.format(*static_cast<const _Tp*>(__ptr), __ctx)); 273 }) {} 274 }; 275 276 #endif //_LIBCPP_STD_VER > 17 277 278 _LIBCPP_END_NAMESPACE_STD 279 280 #endif // _LIBCPP___FORMAT_FORMAT_ARG_H 281