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