File indexing completed on 2026-05-03 08:13:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef _LIBCPP___CXX03___STRING_CONSTEXPR_C_FUNCTIONS_H
0010 #define _LIBCPP___CXX03___STRING_CONSTEXPR_C_FUNCTIONS_H
0011
0012 #include <__cxx03/__config>
0013 #include <__cxx03/__memory/addressof.h>
0014 #include <__cxx03/__memory/construct_at.h>
0015 #include <__cxx03/__type_traits/datasizeof.h>
0016 #include <__cxx03/__type_traits/is_always_bitcastable.h>
0017 #include <__cxx03/__type_traits/is_assignable.h>
0018 #include <__cxx03/__type_traits/is_constant_evaluated.h>
0019 #include <__cxx03/__type_traits/is_constructible.h>
0020 #include <__cxx03/__type_traits/is_equality_comparable.h>
0021 #include <__cxx03/__type_traits/is_same.h>
0022 #include <__cxx03/__type_traits/is_trivially_copyable.h>
0023 #include <__cxx03/__type_traits/is_trivially_lexicographically_comparable.h>
0024 #include <__cxx03/__type_traits/remove_cv.h>
0025 #include <__cxx03/__utility/is_pointer_in_range.h>
0026 #include <__cxx03/cstddef>
0027
0028 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0029 # pragma GCC system_header
0030 #endif
0031
0032 _LIBCPP_BEGIN_NAMESPACE_STD
0033
0034
0035
0036 enum class __element_count : size_t {};
0037
0038 template <class _Tp>
0039 inline const bool __is_char_type = false;
0040
0041 template <>
0042 inline const bool __is_char_type<char> = true;
0043
0044 #ifndef _LIBCPP_HAS_NO_CHAR8_T
0045 template <>
0046 inline const bool __is_char_type<char8_t> = true;
0047 #endif
0048
0049 template <class _Tp>
0050 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const _Tp* __str) _NOEXCEPT {
0051 static_assert(__is_char_type<_Tp>, "__constexpr_strlen only works with char and char8_t");
0052
0053
0054 if (__libcpp_is_constant_evaluated()) {
0055 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_COMPILER_CLANG_BASED)
0056 if constexpr (is_same_v<_Tp, char>)
0057 return __builtin_strlen(__str);
0058 #endif
0059 size_t __i = 0;
0060 for (; __str[__i] != '\0'; ++__i)
0061 ;
0062 return __i;
0063 }
0064 return __builtin_strlen(reinterpret_cast<const char*>(__str));
0065 }
0066
0067
0068
0069
0070 template <class _Tp, class _Up>
0071 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
0072 __constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
0073 static_assert(__libcpp_is_trivially_lexicographically_comparable<_Tp, _Up>::value,
0074 "_Tp and _Up have to be trivially lexicographically comparable");
0075
0076 auto __count = static_cast<size_t>(__n);
0077
0078 if (__libcpp_is_constant_evaluated()) {
0079 #ifdef _LIBCPP_COMPILER_CLANG_BASED
0080 if (sizeof(_Tp) == 1 && !is_same<_Tp, bool>::value)
0081 return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
0082 #endif
0083
0084 while (__count != 0) {
0085 if (*__lhs < *__rhs)
0086 return -1;
0087 if (*__rhs < *__lhs)
0088 return 1;
0089
0090 --__count;
0091 ++__lhs;
0092 ++__rhs;
0093 }
0094 return 0;
0095 } else {
0096 return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
0097 }
0098 }
0099
0100
0101
0102
0103 template <class _Tp, class _Up>
0104 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
0105 __constexpr_memcmp_equal(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
0106 static_assert(__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
0107 "_Tp and _Up have to be trivially equality comparable");
0108
0109 auto __count = static_cast<size_t>(__n);
0110
0111 if (__libcpp_is_constant_evaluated()) {
0112 #ifdef _LIBCPP_COMPILER_CLANG_BASED
0113 if (sizeof(_Tp) == 1 && is_integral<_Tp>::value && !is_same<_Tp, bool>::value)
0114 return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
0115 #endif
0116 while (__count != 0) {
0117 if (*__lhs != *__rhs)
0118 return false;
0119
0120 --__count;
0121 ++__lhs;
0122 ++__rhs;
0123 }
0124 return true;
0125 } else {
0126 return ::__builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
0127 }
0128 }
0129
0130 template <class _Tp, class _Up>
0131 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_memchr(_Tp* __str, _Up __value, size_t __count) {
0132 static_assert(sizeof(_Tp) == 1 && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
0133 "Calling memchr on non-trivially equality comparable types is unsafe.");
0134
0135 if (__libcpp_is_constant_evaluated()) {
0136
0137 #if _LIBCPP_STD_VER >= 17 && __has_builtin(__builtin_char_memchr)
0138 if constexpr (is_same_v<remove_cv_t<_Tp>, char> && is_same_v<remove_cv_t<_Up>, char>)
0139 return __builtin_char_memchr(__str, __value, __count);
0140 #endif
0141
0142 for (; __count; --__count) {
0143 if (*__str == __value)
0144 return __str;
0145 ++__str;
0146 }
0147 return nullptr;
0148 } else {
0149 char __value_buffer = 0;
0150 __builtin_memcpy(&__value_buffer, &__value, sizeof(char));
0151 return static_cast<_Tp*>(__builtin_memchr(__str, __value_buffer, __count));
0152 }
0153 }
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 template <class _Tp, class _Up, __enable_if_t<is_assignable<_Tp&, _Up const&>::value, int> = 0>
0166 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up const& __src) {
0167 __dest = __src;
0168 return __dest;
0169 }
0170
0171
0172 template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value &&
0173 is_assignable<_Tp&, _Up&&>::value, int> = 0>
0174
0175 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up& __src) {
0176 __dest =
0177 static_cast<_Up&&>(__src);
0178 return __dest;
0179 }
0180
0181
0182 template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value &&
0183 !is_assignable<_Tp&, _Up&&>::value &&
0184 is_constructible<_Tp, _Up const&>::value, int> = 0>
0185
0186 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up const& __src) {
0187
0188
0189 std::__construct_at(std::addressof(__dest), __src);
0190 return __dest;
0191 }
0192
0193
0194 template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value &&
0195 !is_assignable<_Tp&, _Up&&>::value &&
0196 !is_constructible<_Tp, _Up const&>::value &&
0197 is_constructible<_Tp, _Up&&>::value, int> = 0>
0198
0199 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up& __src) {
0200
0201
0202 std::__construct_at(
0203 std::addressof(__dest),
0204 static_cast<_Up&&>(__src));
0205 return __dest;
0206 }
0207
0208 template <class _Tp, class _Up, __enable_if_t<__is_always_bitcastable<_Up, _Tp>::value, int> = 0>
0209 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp*
0210 __constexpr_memmove(_Tp* __dest, _Up* __src, __element_count __n) {
0211 size_t __count = static_cast<size_t>(__n);
0212 if (__libcpp_is_constant_evaluated()) {
0213 #ifdef _LIBCPP_COMPILER_CLANG_BASED
0214 if (is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value) {
0215 ::__builtin_memmove(__dest, __src, __count * sizeof(_Tp));
0216 return __dest;
0217 }
0218 #endif
0219 if (std::__is_pointer_in_range(__src, __src + __count, __dest)) {
0220 for (; __count > 0; --__count)
0221 std::__assign_trivially_copyable(__dest[__count - 1], __src[__count - 1]);
0222 } else {
0223 for (size_t __i = 0; __i != __count; ++__i)
0224 std::__assign_trivially_copyable(__dest[__i], __src[__i]);
0225 }
0226 } else if (__count > 0) {
0227 ::__builtin_memmove(__dest, __src, (__count - 1) * sizeof(_Tp) + __datasizeof_v<_Tp>);
0228 }
0229 return __dest;
0230 }
0231
0232 _LIBCPP_END_NAMESPACE_STD
0233
0234 #endif