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