Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:49

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___FORMAT_FORMAT_ARG_STORE_H
0011 #define _LIBCPP___FORMAT_FORMAT_ARG_STORE_H
0012 
0013 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0014 #  pragma GCC system_header
0015 #endif
0016 
0017 #include <__concepts/arithmetic.h>
0018 #include <__concepts/same_as.h>
0019 #include <__config>
0020 #include <__format/concepts.h>
0021 #include <__format/format_arg.h>
0022 #include <__type_traits/conditional.h>
0023 #include <__type_traits/extent.h>
0024 #include <__type_traits/remove_const.h>
0025 #include <cstdint>
0026 #include <string>
0027 #include <string_view>
0028 
0029 _LIBCPP_BEGIN_NAMESPACE_STD
0030 
0031 #if _LIBCPP_STD_VER >= 20
0032 
0033 namespace __format {
0034 
0035 /// \returns The @c __arg_t based on the type of the formatting argument.
0036 ///
0037 /// \pre \c __formattable<_Tp, typename _Context::char_type>
0038 template <class _Context, class _Tp>
0039 consteval __arg_t __determine_arg_t();
0040 
0041 // Boolean
0042 template <class, same_as<bool> _Tp>
0043 consteval __arg_t __determine_arg_t() {
0044   return __arg_t::__boolean;
0045 }
0046 
0047 // Char
0048 template <class _Context, same_as<typename _Context::char_type> _Tp>
0049 consteval __arg_t __determine_arg_t() {
0050   return __arg_t::__char_type;
0051 }
0052 #  if _LIBCPP_HAS_WIDE_CHARACTERS
0053 template <class _Context, class _CharT>
0054   requires(same_as<typename _Context::char_type, wchar_t> && same_as<_CharT, char>)
0055 consteval __arg_t __determine_arg_t() {
0056   return __arg_t::__char_type;
0057 }
0058 #  endif
0059 
0060 // Signed integers
0061 template <class, __libcpp_signed_integer _Tp>
0062 consteval __arg_t __determine_arg_t() {
0063   if constexpr (sizeof(_Tp) <= sizeof(int))
0064     return __arg_t::__int;
0065   else if constexpr (sizeof(_Tp) <= sizeof(long long))
0066     return __arg_t::__long_long;
0067 #  if _LIBCPP_HAS_INT128
0068   else if constexpr (sizeof(_Tp) == sizeof(__int128_t))
0069     return __arg_t::__i128;
0070 #  endif
0071   else
0072     static_assert(sizeof(_Tp) == 0, "an unsupported signed integer was used");
0073 }
0074 
0075 // Unsigned integers
0076 template <class, __libcpp_unsigned_integer _Tp>
0077 consteval __arg_t __determine_arg_t() {
0078   if constexpr (sizeof(_Tp) <= sizeof(unsigned))
0079     return __arg_t::__unsigned;
0080   else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long))
0081     return __arg_t::__unsigned_long_long;
0082 #  if _LIBCPP_HAS_INT128
0083   else if constexpr (sizeof(_Tp) == sizeof(__uint128_t))
0084     return __arg_t::__u128;
0085 #  endif
0086   else
0087     static_assert(sizeof(_Tp) == 0, "an unsupported unsigned integer was used");
0088 }
0089 
0090 // Floating-point
0091 template <class, same_as<float> _Tp>
0092 consteval __arg_t __determine_arg_t() {
0093   return __arg_t::__float;
0094 }
0095 template <class, same_as<double> _Tp>
0096 consteval __arg_t __determine_arg_t() {
0097   return __arg_t::__double;
0098 }
0099 template <class, same_as<long double> _Tp>
0100 consteval __arg_t __determine_arg_t() {
0101   return __arg_t::__long_double;
0102 }
0103 
0104 // Char pointer
0105 template <class _Context, class _Tp>
0106   requires(same_as<typename _Context::char_type*, _Tp> || same_as<const typename _Context::char_type*, _Tp>)
0107 consteval __arg_t __determine_arg_t() {
0108   return __arg_t::__const_char_type_ptr;
0109 }
0110 
0111 // Char array
0112 template <class _Context, class _Tp>
0113   requires(is_array_v<_Tp> && same_as<_Tp, typename _Context::char_type[extent_v<_Tp>]>)
0114 consteval __arg_t __determine_arg_t() {
0115   return __arg_t::__string_view;
0116 }
0117 
0118 // String view
0119 template <class _Context, class _Tp>
0120   requires(same_as<typename _Context::char_type, typename _Tp::value_type> &&
0121            same_as<_Tp, basic_string_view<typename _Tp::value_type, typename _Tp::traits_type>>)
0122 consteval __arg_t __determine_arg_t() {
0123   return __arg_t::__string_view;
0124 }
0125 
0126 // String
0127 template <class _Context, class _Tp>
0128   requires(
0129       same_as<typename _Context::char_type, typename _Tp::value_type> &&
0130       same_as<_Tp, basic_string<typename _Tp::value_type, typename _Tp::traits_type, typename _Tp::allocator_type>>)
0131 consteval __arg_t __determine_arg_t() {
0132   return __arg_t::__string_view;
0133 }
0134 
0135 // Pointers
0136 template <class, class _Ptr>
0137   requires(same_as<_Ptr, void*> || same_as<_Ptr, const void*> || same_as<_Ptr, nullptr_t>)
0138 consteval __arg_t __determine_arg_t() {
0139   return __arg_t::__ptr;
0140 }
0141 
0142 // Handle
0143 //
0144 // Note this version can't be constrained avoiding ambiguous overloads.
0145 // That means it can be instantiated by disabled formatters. To solve this, a
0146 // constrained version for not formattable formatters is added.
0147 template <class _Context, class _Tp>
0148 consteval __arg_t __determine_arg_t() {
0149   return __arg_t::__handle;
0150 }
0151 
0152 // The overload for not formattable types allows triggering the static
0153 // assertion below.
0154 template <class _Context, class _Tp>
0155   requires(!__formattable_with<_Tp, _Context>)
0156 consteval __arg_t __determine_arg_t() {
0157   return __arg_t::__none;
0158 }
0159 
0160 // Pseudo constuctor for basic_format_arg
0161 //
0162 // Modeled after template<class T> explicit basic_format_arg(T& v) noexcept;
0163 // [format.arg]/4-6
0164 template <class _Context, class _Tp>
0165 _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __value) noexcept {
0166   using _Dp               = remove_const_t<_Tp>;
0167   constexpr __arg_t __arg = __determine_arg_t<_Context, _Dp>();
0168   static_assert(__arg != __arg_t::__none, "the supplied type is not formattable");
0169   static_assert(__formattable_with<_Tp, _Context>);
0170 
0171   // Not all types can be used to directly initialize the
0172   // __basic_format_arg_value.  First handle all types needing adjustment, the
0173   // final else requires no adjustment.
0174   if constexpr (__arg == __arg_t::__char_type)
0175 
0176 #  if _LIBCPP_HAS_WIDE_CHARACTERS
0177     if constexpr (same_as<typename _Context::char_type, wchar_t> && same_as<_Dp, char>)
0178       return basic_format_arg<_Context>{__arg, static_cast<wchar_t>(static_cast<unsigned char>(__value))};
0179     else
0180 #  endif
0181       return basic_format_arg<_Context>{__arg, __value};
0182   else if constexpr (__arg == __arg_t::__int)
0183     return basic_format_arg<_Context>{__arg, static_cast<int>(__value)};
0184   else if constexpr (__arg == __arg_t::__long_long)
0185     return basic_format_arg<_Context>{__arg, static_cast<long long>(__value)};
0186   else if constexpr (__arg == __arg_t::__unsigned)
0187     return basic_format_arg<_Context>{__arg, static_cast<unsigned>(__value)};
0188   else if constexpr (__arg == __arg_t::__unsigned_long_long)
0189     return basic_format_arg<_Context>{__arg, static_cast<unsigned long long>(__value)};
0190   else if constexpr (__arg == __arg_t::__string_view)
0191     // Using std::size on a character array will add the NUL-terminator to the size.
0192     if constexpr (is_array_v<_Dp>)
0193       return basic_format_arg<_Context>{
0194           __arg, basic_string_view<typename _Context::char_type>{__value, extent_v<_Dp> - 1}};
0195     else
0196       // When the _Traits or _Allocator are different an implicit conversion will
0197       // fail.
0198       return basic_format_arg<_Context>{
0199           __arg, basic_string_view<typename _Context::char_type>{__value.data(), __value.size()}};
0200   else if constexpr (__arg == __arg_t::__ptr)
0201     return basic_format_arg<_Context>{__arg, static_cast<const void*>(__value)};
0202   else if constexpr (__arg == __arg_t::__handle)
0203     return basic_format_arg<_Context>{__arg, typename __basic_format_arg_value<_Context>::__handle{__value}};
0204   else
0205     return basic_format_arg<_Context>{__arg, __value};
0206 }
0207 
0208 template <class _Context, class... _Args>
0209 _LIBCPP_HIDE_FROM_ABI void
0210 __create_packed_storage(uint64_t& __types, __basic_format_arg_value<_Context>* __values, _Args&... __args) noexcept {
0211   int __shift = 0;
0212   (
0213       [&] {
0214         basic_format_arg<_Context> __arg = __format::__create_format_arg<_Context>(__args);
0215         if (__shift != 0)
0216           __types |= static_cast<uint64_t>(__arg.__type_) << __shift;
0217         else
0218           // Assigns the initial value.
0219           __types = static_cast<uint64_t>(__arg.__type_);
0220         __shift += __packed_arg_t_bits;
0221         *__values++ = __arg.__value_;
0222       }(),
0223       ...);
0224 }
0225 
0226 template <class _Context, class... _Args>
0227 _LIBCPP_HIDE_FROM_ABI void __store_basic_format_arg(basic_format_arg<_Context>* __data, _Args&... __args) noexcept {
0228   ([&] { *__data++ = __format::__create_format_arg<_Context>(__args); }(), ...);
0229 }
0230 
0231 template <class _Context, size_t _Np>
0232 struct __packed_format_arg_store {
0233   __basic_format_arg_value<_Context> __values_[_Np];
0234   uint64_t __types_ = 0;
0235 };
0236 
0237 template <class _Context>
0238 struct __packed_format_arg_store<_Context, 0> {
0239   uint64_t __types_ = 0;
0240 };
0241 
0242 template <class _Context, size_t _Np>
0243 struct __unpacked_format_arg_store {
0244   basic_format_arg<_Context> __args_[_Np];
0245 };
0246 
0247 } // namespace __format
0248 
0249 template <class _Context, class... _Args>
0250 struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
0251   _LIBCPP_HIDE_FROM_ABI __format_arg_store(_Args&... __args) noexcept {
0252     if constexpr (sizeof...(_Args) != 0) {
0253       if constexpr (__format::__use_packed_format_arg_store(sizeof...(_Args)))
0254         __format::__create_packed_storage(__storage.__types_, __storage.__values_, __args...);
0255       else
0256         __format::__store_basic_format_arg<_Context>(__storage.__args_, __args...);
0257     }
0258   }
0259 
0260   using _Storage _LIBCPP_NODEBUG =
0261       conditional_t<__format::__use_packed_format_arg_store(sizeof...(_Args)),
0262                     __format::__packed_format_arg_store<_Context, sizeof...(_Args)>,
0263                     __format::__unpacked_format_arg_store<_Context, sizeof...(_Args)>>;
0264 
0265   _Storage __storage;
0266 };
0267 
0268 #endif // _LIBCPP_STD_VER >= 20
0269 
0270 _LIBCPP_END_NAMESPACE_STD
0271 
0272 #endif // _LIBCPP___FORMAT_FORMAT_ARG_STORE_H