[INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides: - CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk) - Thrust: high-level parallel algorithms (transform_reduce, sort, scan) - libcudacxx: CUDA C++ standard library (atomics, barriers, memory) - cudax: experimental features (memory resources, allocators) - Tuning policies: per-SM hardware-specific algorithm parameters Competition optimization vectors mapped to CCCL: - Output TPS (83% weight): warp_reduce, block_reduce, device_topk - Input TPS (14% weight): device_scan, block_load, prefetch - Cache TPS (3% weight): prefix caching strategy patterns - Memory (0.9 util): pooled/cached/buddy allocators Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only) License: Apache-2.0
This commit is contained in:
190
cccl_upstream/libcudacxx/include/cuda/std/__string/char_traits.h
Normal file
190
cccl_upstream/libcudacxx/include/cuda/std/__string/char_traits.h
Normal file
@@ -0,0 +1,190 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA_STD___STRING_CHAR_TRAITS_H
|
||||
#define _CUDA_STD___STRING_CHAR_TRAITS_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__cstddef/types.h>
|
||||
#include <cuda/std/__fwd/char_traits.h>
|
||||
#include <cuda/std/__string/constexpr_c_functions.h>
|
||||
#include <cuda/std/__type_traits/is_same.h>
|
||||
#include <cuda/std/cstdint>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA_STD
|
||||
|
||||
template <class _CharT, class _IntT, _IntT _EOFVal = _IntT(-1) /*todo: remove default argument*/>
|
||||
struct __cccl_char_traits_impl
|
||||
{
|
||||
using char_type = _CharT;
|
||||
using int_type = _IntT;
|
||||
#if 0 // todo: add stream support
|
||||
using off_type = streamoff;
|
||||
using pos_type = fpos<mbstate_t>;
|
||||
using state_type = mbstate_t;
|
||||
#endif
|
||||
#if _LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
|
||||
using comparison_category = strong_ordering;
|
||||
#endif // _LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
|
||||
|
||||
_CCCL_API static constexpr void assign(char_type& __lhs, const char_type& __rhs) noexcept
|
||||
{
|
||||
__lhs = __rhs;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr bool eq(char_type __lhs, char_type __rhs) noexcept
|
||||
{
|
||||
return __lhs == __rhs;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr bool lt(char_type __lhs, char_type __rhs) noexcept
|
||||
{
|
||||
if constexpr (is_same_v<char_type, char>)
|
||||
{
|
||||
return static_cast<unsigned char>(__lhs) < static_cast<unsigned char>(__rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return __lhs < __rhs;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr int
|
||||
compare(const char_type* __lhs, const char_type* __rhs, size_t __count) noexcept
|
||||
{
|
||||
if (__count > 0)
|
||||
{
|
||||
_CCCL_ASSERT(__lhs != nullptr, "char_traits::compare: lhs pointer is null");
|
||||
_CCCL_ASSERT(__rhs != nullptr, "char_traits::compare: rhs pointer is null");
|
||||
}
|
||||
return ::cuda::std::__cccl_memcmp(__lhs, __rhs, __count);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API inline static size_t constexpr length(const char_type* __s) noexcept
|
||||
{
|
||||
_CCCL_ASSERT(__s != nullptr, "char_traits::length: nullptr passed as an argument");
|
||||
return ::cuda::std::__cccl_strlen(__s);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr const char_type*
|
||||
find(const char_type* __s, size_t __n, const char_type& __a) noexcept
|
||||
{
|
||||
if (__n > 0)
|
||||
{
|
||||
_CCCL_ASSERT(__s != nullptr, "char_traits::find: nullptr passed as an argument");
|
||||
}
|
||||
return ::cuda::std::__cccl_memchr<const char_type>(__s, __a, __n);
|
||||
}
|
||||
|
||||
_CCCL_API static constexpr char_type* move(char_type* __s1, const char_type* __s2, size_t __n) noexcept
|
||||
{
|
||||
if (__n > 0)
|
||||
{
|
||||
_CCCL_ASSERT(__s1 != nullptr, "char_traits::move: destination pointer is null");
|
||||
_CCCL_ASSERT(__s2 != nullptr, "char_traits::move: source pointer is null");
|
||||
}
|
||||
return ::cuda::std::__cccl_memmove(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
_CCCL_API static constexpr char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) noexcept
|
||||
{
|
||||
if (__n > 0)
|
||||
{
|
||||
_CCCL_ASSERT(__s1 != nullptr, "char_traits::copy: destination pointer is null");
|
||||
_CCCL_ASSERT(__s2 != nullptr, "char_traits::copy: source pointer is null");
|
||||
}
|
||||
return ::cuda::std::__cccl_memcpy(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
_CCCL_API static constexpr char_type* assign(char_type* __s, size_t __n, char_type __a) noexcept
|
||||
{
|
||||
if (__n > 0)
|
||||
{
|
||||
_CCCL_ASSERT(__s != nullptr, "char_traits::assign: destination pointer is null");
|
||||
}
|
||||
return ::cuda::std::__cccl_memset(__s, __a, __n);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr char_type to_char_type(int_type __c) noexcept
|
||||
{
|
||||
return char_type(__c);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr int_type to_int_type(char_type __c) noexcept
|
||||
{
|
||||
if constexpr (is_same_v<char_type, char>)
|
||||
{
|
||||
return int_type(static_cast<unsigned char>(__c));
|
||||
}
|
||||
else
|
||||
{
|
||||
return int_type(__c);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr bool eq_int_type(int_type __lhs, int_type __rhs) noexcept
|
||||
{
|
||||
return __lhs == __rhs;
|
||||
}
|
||||
|
||||
#if 0 // todo: add EOF support
|
||||
[[nodiscard]] _CCCL_API static constexpr int_type eof() noexcept
|
||||
{
|
||||
return _EOFVal;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr int_type not_eof(int_type __c) noexcept
|
||||
{
|
||||
return eq_int_type(__c, eof()) ? static_cast<int_type>(~eof()) : __c;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT char_traits<char> : __cccl_char_traits_impl<char, int /*, EOF*/>
|
||||
{};
|
||||
|
||||
#if _CCCL_HAS_CHAR8_T()
|
||||
template <>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT char_traits<char8_t> : __cccl_char_traits_impl<char8_t, unsigned /*, ??? */>
|
||||
{};
|
||||
#endif // _CCCL_HAS_CHAR8_T()
|
||||
|
||||
template <>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT
|
||||
char_traits<char16_t> : __cccl_char_traits_impl<char16_t, uint_least16_t /*, ??? */>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT
|
||||
char_traits<char32_t> : __cccl_char_traits_impl<char32_t, uint_least32_t /*, ??? */>
|
||||
{};
|
||||
|
||||
#if _CCCL_HAS_WCHAR_T()
|
||||
template <>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT char_traits<wchar_t> : __cccl_char_traits_impl<wchar_t, wint_t /*, WEOF*/>
|
||||
{};
|
||||
#endif // _CCCL_HAS_WCHAR_T()
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA_STD
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA_STD___STRING_CHAR_TRAITS_H
|
||||
@@ -0,0 +1,595 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA_STD___STRING_CONSTEXPR_C_FUNCTIONS_H
|
||||
#define _CUDA_STD___STRING_CONSTEXPR_C_FUNCTIONS_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__cstddef/types.h>
|
||||
#include <cuda/std/__type_traits/make_nbit_int.h>
|
||||
#include <cuda/std/__type_traits/remove_const.h>
|
||||
#include <cuda/std/climits>
|
||||
|
||||
#if _CCCL_HOSTED()
|
||||
# include <cstring>
|
||||
#elif _CCCL_HOSTJIT()
|
||||
# include <string.h>
|
||||
#endif // _CCCL_HOSTJIT()
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA_STD
|
||||
|
||||
// __cccl_strcpy
|
||||
|
||||
template <class _CharT>
|
||||
_CCCL_API constexpr _CharT*
|
||||
__cccl_strcpy_impl_constexpr(_CharT* _CCCL_RESTRICT __dst, const _CharT* _CCCL_RESTRICT __src) noexcept
|
||||
{
|
||||
_CharT* __dst_it = __dst;
|
||||
while ((*__dst_it++ = *__src++) != _CharT('\0'))
|
||||
{
|
||||
}
|
||||
return __dst;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _CharT>
|
||||
_CCCL_HOST_API _CharT* __cccl_strcpy_impl_host(_CharT* _CCCL_RESTRICT __dst, const _CharT* _CCCL_RESTRICT __src) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_CharT) == 1)
|
||||
{
|
||||
return reinterpret_cast<_CharT*>(::strcpy(reinterpret_cast<char*>(__dst), reinterpret_cast<const char*>(__src)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_strcpy_impl_constexpr(__dst, __src);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _CharT>
|
||||
_CCCL_API constexpr _CharT* __cccl_strcpy(_CharT* _CCCL_RESTRICT __dst, const _CharT* _CCCL_RESTRICT __src) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_strcpy_impl_host(__dst, __src);))
|
||||
}
|
||||
return ::cuda::std::__cccl_strcpy_impl_constexpr(__dst, __src);
|
||||
}
|
||||
|
||||
// __cccl_strncpy
|
||||
|
||||
template <class _CharT>
|
||||
_CCCL_API constexpr _CharT*
|
||||
__cccl_strncpy_impl_constexpr(_CharT* _CCCL_RESTRICT __dst, const _CharT* _CCCL_RESTRICT __src, size_t __n) noexcept
|
||||
{
|
||||
_CharT* __dst_it = __dst;
|
||||
while (__n--)
|
||||
{
|
||||
if ((*__dst_it++ = *__src++) == _CharT('\0')) // NOLINT(bugprone-assignment-in-if-condition)
|
||||
{
|
||||
while (__n--)
|
||||
{
|
||||
*__dst_it++ = _CharT('\0');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __dst;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _CharT>
|
||||
_CCCL_HOST_API _CharT*
|
||||
__cccl_strncpy_impl_host(_CharT* _CCCL_RESTRICT __dst, const _CharT* _CCCL_RESTRICT __src, size_t __n) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_CharT) == 1)
|
||||
{
|
||||
return reinterpret_cast<_CharT*>(
|
||||
::strncpy(reinterpret_cast<char*>(__dst), reinterpret_cast<const char*>(__src), __n));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_strncpy_impl_constexpr(__dst, __src, __n);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _CharT>
|
||||
_CCCL_API constexpr _CharT*
|
||||
__cccl_strncpy(_CharT* _CCCL_RESTRICT __dst, const _CharT* _CCCL_RESTRICT __src, size_t __n) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_strncpy_impl_host(__dst, __src, __n);))
|
||||
}
|
||||
return ::cuda::std::__cccl_strncpy_impl_constexpr(__dst, __src, __n);
|
||||
}
|
||||
|
||||
// __cccl_strlen
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr size_t __cccl_strlen_impl_constexpr(const _CharT* __ptr) noexcept
|
||||
{
|
||||
size_t __len = 0;
|
||||
while (*__ptr++ != _CharT('\0'))
|
||||
{
|
||||
++__len;
|
||||
}
|
||||
return __len;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_HOST_API size_t __cccl_strlen_impl_host(const _CharT* __ptr) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_CharT) == 1)
|
||||
{
|
||||
return ::strlen(reinterpret_cast<const char*>(__ptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_strlen_impl_constexpr(__ptr);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr size_t __cccl_strlen(const _CharT* __ptr) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_strlen_impl_host(__ptr);))
|
||||
}
|
||||
return ::cuda::std::__cccl_strlen_impl_constexpr(__ptr);
|
||||
}
|
||||
|
||||
// __cccl_strcmp
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr int __cccl_strcmp_impl_constexpr(const _CharT* __lhs, const _CharT* __rhs) noexcept
|
||||
{
|
||||
using _UCharT = __make_nbit_uint_t<sizeof(_CharT) * CHAR_BIT>;
|
||||
|
||||
bool __reached_end = false;
|
||||
while (*__lhs == *__rhs)
|
||||
{
|
||||
if (*__lhs == _CharT('\0'))
|
||||
{
|
||||
__reached_end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
++__lhs;
|
||||
++__rhs;
|
||||
}
|
||||
return __reached_end ? 0 : (static_cast<_UCharT>(*__lhs) < static_cast<_UCharT>(*__rhs)) ? -1 : 1;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_HOST_API int __cccl_strcmp_impl_host(const _CharT* __lhs, const _CharT* __rhs) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_CharT) == 1)
|
||||
{
|
||||
return ::strcmp(reinterpret_cast<const char*>(__lhs), reinterpret_cast<const char*>(__rhs));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_strcmp_impl_constexpr(__lhs, __rhs);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr int __cccl_strcmp(const _CharT* __lhs, const _CharT* __rhs) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_strcmp_impl_host(__lhs, __rhs);))
|
||||
}
|
||||
return ::cuda::std::__cccl_strcmp_impl_constexpr(__lhs, __rhs);
|
||||
}
|
||||
|
||||
// __cccl_strncmp
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr int
|
||||
__cccl_strncmp_impl_constexpr(const _CharT* __lhs, const _CharT* __rhs, size_t __n) noexcept
|
||||
{
|
||||
using _UCharT = __make_nbit_uint_t<sizeof(_CharT) * CHAR_BIT>;
|
||||
|
||||
int __result = 0;
|
||||
while (__n--)
|
||||
{
|
||||
if (*__lhs != *__rhs)
|
||||
{
|
||||
__result = (static_cast<_UCharT>(*__lhs) < static_cast<_UCharT>(*__rhs)) ? -1 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*__lhs == _CharT('\0'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++__lhs;
|
||||
++__rhs;
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_HOST_API int __cccl_strncmp_impl_host(const _CharT* __lhs, const _CharT* __rhs, size_t __n) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_CharT) == 1)
|
||||
{
|
||||
return ::strncmp(reinterpret_cast<const char*>(__lhs), reinterpret_cast<const char*>(__rhs), __n);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_strncmp_impl_constexpr(__lhs, __rhs, __n);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr int __cccl_strncmp(const _CharT* __lhs, const _CharT* __rhs, size_t __n) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_strncmp_impl_host(__lhs, __rhs, __n);))
|
||||
}
|
||||
return ::cuda::std::__cccl_strncmp_impl_constexpr(__lhs, __rhs, __n);
|
||||
}
|
||||
|
||||
// __cccl_strchr
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr _CharT* __cccl_strchr_impl_constexpr(_CharT* __ptr, _CharT __c) noexcept
|
||||
{
|
||||
bool __reached_end = false;
|
||||
while (*__ptr != __c)
|
||||
{
|
||||
if (*__ptr == _CharT('\0'))
|
||||
{
|
||||
__reached_end = true;
|
||||
break;
|
||||
}
|
||||
++__ptr;
|
||||
}
|
||||
return __reached_end ? nullptr : __ptr;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_HOST_API _CharT* __cccl_strchr_impl_host(_CharT* __ptr, _CharT __c) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_CharT) == 1)
|
||||
{
|
||||
using _Up = remove_const_t<_CharT>;
|
||||
return const_cast<_CharT*>(
|
||||
reinterpret_cast<_Up*>(::strchr(reinterpret_cast<char*>(const_cast<_Up*>(__ptr)), static_cast<int>(__c))));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_strchr_impl_constexpr<_CharT>(__ptr, __c);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr _CharT* __cccl_strchr(_CharT* __ptr, _CharT __c) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_strchr_impl_host<_CharT>(__ptr, __c);))
|
||||
}
|
||||
return ::cuda::std::__cccl_strchr_impl_constexpr<_CharT>(__ptr, __c);
|
||||
}
|
||||
|
||||
// __cccl_strrchr
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr _CharT* __cccl_strrchr_impl_constexpr(_CharT* __ptr, _CharT __c) noexcept
|
||||
{
|
||||
if (__c == _CharT('\0'))
|
||||
{
|
||||
return __ptr + ::cuda::std::__cccl_strlen(__ptr);
|
||||
}
|
||||
|
||||
_CharT* __last{};
|
||||
while (*__ptr != _CharT('\0'))
|
||||
{
|
||||
if (*__ptr == __c)
|
||||
{
|
||||
__last = __ptr;
|
||||
}
|
||||
++__ptr;
|
||||
}
|
||||
return __last;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_HOST_API _CharT* __cccl_strrchr_impl_host(_CharT* __ptr, _CharT __c) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_CharT) == 1)
|
||||
{
|
||||
using _Up = remove_const_t<_CharT>;
|
||||
return const_cast<_CharT*>(
|
||||
reinterpret_cast<_Up*>(::strrchr(reinterpret_cast<char*>(const_cast<_Up*>(__ptr)), static_cast<int>(__c))));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_strrchr_impl_constexpr<_CharT>(__ptr, __c);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _CharT>
|
||||
[[nodiscard]] _CCCL_API constexpr _CharT* __cccl_strrchr(_CharT* __ptr, _CharT __c) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_strrchr_impl_host<_CharT>(__ptr, __c);))
|
||||
}
|
||||
return ::cuda::std::__cccl_strrchr_impl_constexpr<_CharT>(__ptr, __c);
|
||||
}
|
||||
|
||||
// __cccl_memchr
|
||||
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_API constexpr _Tp* __cccl_memchr_impl_constexpr(_Tp* __ptr, _Tp __c, size_t __n) noexcept
|
||||
{
|
||||
_Tp* __result = nullptr;
|
||||
while (__n--)
|
||||
{
|
||||
if (*__ptr == __c)
|
||||
{
|
||||
__result = __ptr;
|
||||
break;
|
||||
}
|
||||
++__ptr;
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API _Tp* __cccl_memchr_impl_host(_Tp* __ptr, _Tp __c, size_t __n) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_Tp) == 1)
|
||||
{
|
||||
using _Up = remove_const_t<_Tp>;
|
||||
return const_cast<_Tp*>(reinterpret_cast<_Up*>(::memchr(const_cast<_Up*>(__ptr), static_cast<int>(__c), __n)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_memchr_impl_constexpr<_Tp>(__ptr, __c, __n);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_API constexpr _Tp* __cccl_memchr(_Tp* __ptr, _Tp __c, size_t __n) noexcept
|
||||
{
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_memchr_impl_host<_Tp>(__ptr, __c, __n);))
|
||||
}
|
||||
return ::cuda::std::__cccl_memchr_impl_constexpr<_Tp>(__ptr, __c, __n);
|
||||
}
|
||||
|
||||
// __cccl_memmove
|
||||
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_API constexpr _Tp* __cccl_memmove_impl_constexpr(_Tp* __dst, const _Tp* __src, size_t __n) noexcept
|
||||
{
|
||||
const auto __dst_copy = __dst;
|
||||
|
||||
if (__src < __dst && __dst < __src + __n)
|
||||
{
|
||||
__dst += __n;
|
||||
__src += __n;
|
||||
|
||||
while (__n-- > 0)
|
||||
{
|
||||
*--__dst = *--__src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (__n-- > 0)
|
||||
{
|
||||
*__dst++ = *__src++;
|
||||
}
|
||||
}
|
||||
return __dst_copy;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API _Tp* __cccl_memmove_impl_host(_Tp* __dst, const _Tp* __src, size_t __n) noexcept
|
||||
{
|
||||
return reinterpret_cast<_Tp*>(::memmove(__dst, __src, __n * sizeof(_Tp)));
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _Tp>
|
||||
_CCCL_API constexpr _Tp* __cccl_memmove(_Tp* __dst, const _Tp* __src, size_t __n) noexcept
|
||||
{
|
||||
#if !_CCCL_TILE_COMPILATION() // error: "call to non-tile function not supported!"
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
# if defined(_CCCL_BUILTIN_MEMMOVE)
|
||||
return reinterpret_cast<_Tp*>(_CCCL_BUILTIN_MEMMOVE(__dst, __src, __n * sizeof(_Tp)));
|
||||
# else // ^^^ _CCCL_BUILTIN_MEMMOVE ^^^ / vvv !_CCCL_BUILTIN_MEMMOVE vvv
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_memmove_impl_host(__dst, __src, __n);))
|
||||
# endif // ^^^ !_CCCL_BUILTIN_MEMMOVE ^^^
|
||||
}
|
||||
#endif // !_CCCL_TILE_COMPILATION()
|
||||
return ::cuda::std::__cccl_memmove_impl_constexpr(__dst, __src, __n);
|
||||
}
|
||||
|
||||
// __cccl_memcmp
|
||||
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_API constexpr int
|
||||
__cccl_memcmp_impl_constexpr(const _Tp* __lhs, const _Tp* __rhs, size_t __n) noexcept
|
||||
{
|
||||
using _Up = __make_nbit_uint_t<sizeof(_Tp) * CHAR_BIT>;
|
||||
|
||||
int __result = 0;
|
||||
while (__n--)
|
||||
{
|
||||
if (*__lhs != *__rhs)
|
||||
{
|
||||
__result = static_cast<_Up>(*__lhs) < static_cast<_Up>(*__rhs) ? -1 : 1;
|
||||
break;
|
||||
}
|
||||
++__lhs;
|
||||
++__rhs;
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API int __cccl_memcmp_impl_host(const _Tp* __lhs, const _Tp* __rhs, size_t __n) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_Tp) == 1)
|
||||
{
|
||||
return ::memcmp(__lhs, __rhs, __n);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_memcmp_impl_constexpr(__lhs, __rhs, __n);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_API constexpr int __cccl_memcmp(const _Tp* __lhs, const _Tp* __rhs, size_t __n) noexcept
|
||||
{
|
||||
#if !_CCCL_TILE_COMPILATION() // error: "call to non-tile function not supported!"
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
# if defined(_CCCL_BUILTIN_MEMCMP)
|
||||
return _CCCL_BUILTIN_MEMCMP(__lhs, __rhs, __n * sizeof(_Tp));
|
||||
# else // ^^^ _CCCL_BUILTIN_MEMCMP ^^^ / vvv !_CCCL_BUILTIN_MEMCMP vvv
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_memcmp_impl_host(__lhs, __rhs, __n);))
|
||||
# endif // ^^^ !_CCCL_BUILTIN_MEMCMP ^^^
|
||||
}
|
||||
#endif // !_CCCL_TILE_COMPILATION()
|
||||
return ::cuda::std::__cccl_memcmp_impl_constexpr(__lhs, __rhs, __n);
|
||||
}
|
||||
|
||||
// __cccl_memcpy
|
||||
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_API constexpr _Tp*
|
||||
__cccl_memcpy_impl_constexpr(_Tp* _CCCL_RESTRICT __dst, const _Tp* _CCCL_RESTRICT __src, size_t __n) noexcept
|
||||
{
|
||||
const auto __dst_copy = __dst;
|
||||
|
||||
while (__n--)
|
||||
{
|
||||
*__dst++ = *__src++;
|
||||
}
|
||||
return __dst_copy;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API _Tp*
|
||||
__cccl_memcpy_impl_host(_Tp* _CCCL_RESTRICT __dst, const _Tp* _CCCL_RESTRICT __src, size_t __n) noexcept
|
||||
{
|
||||
return reinterpret_cast<_Tp*>(::memcpy(__dst, __src, __n * sizeof(_Tp)));
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _Tp>
|
||||
_CCCL_API constexpr _Tp* __cccl_memcpy(_Tp* _CCCL_RESTRICT __dst, const _Tp* _CCCL_RESTRICT __src, size_t __n) noexcept
|
||||
{
|
||||
#if !_CCCL_TILE_COMPILATION() // error: "call to non-tile function not supported!"
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
# if defined(_CCCL_BUILTIN_MEMCPY)
|
||||
return reinterpret_cast<_Tp*>(_CCCL_BUILTIN_MEMCPY(__dst, __src, __n * sizeof(_Tp)));
|
||||
# else // ^^^ _CCCL_BUILTIN_MEMCPY ^^^ / vvv !_CCCL_BUILTIN_MEMCPY vvv
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_memcpy_impl_host(__dst, __src, __n);))
|
||||
# endif // ^^^ !_CCCL_BUILTIN_MEMCPY ^^^
|
||||
}
|
||||
#endif // !_CCCL_TILE_COMPILATION()
|
||||
return ::cuda::std::__cccl_memcpy_impl_constexpr(__dst, __src, __n);
|
||||
}
|
||||
|
||||
// __cccl_memset
|
||||
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_API constexpr _Tp* __cccl_memset_impl_constexpr(_Tp* __ptr, _Tp __c, size_t __n) noexcept
|
||||
{
|
||||
const auto __ptr_copy = __ptr;
|
||||
|
||||
while (__n--)
|
||||
{
|
||||
*__ptr++ = __c;
|
||||
}
|
||||
return __ptr_copy;
|
||||
}
|
||||
|
||||
#if !_CCCL_COMPILER(NVRTC)
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API _Tp* __cccl_memset_impl_host(_Tp* __ptr, _Tp __c, size_t __n) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_Tp) == 1)
|
||||
{
|
||||
return reinterpret_cast<_Tp*>(::memset(__ptr, static_cast<int>(__c), __n));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ::cuda::std::__cccl_memset_impl_constexpr(__ptr, __c, __n);
|
||||
}
|
||||
}
|
||||
#endif // !_CCCL_COMPILER(NVRTC)
|
||||
|
||||
template <class _Tp>
|
||||
_CCCL_API constexpr _Tp* __cccl_memset(_Tp* __ptr, _Tp __c, size_t __n) noexcept
|
||||
{
|
||||
#if !_CCCL_TILE_COMPILATION() // error: "call to non-tile function not supported!"
|
||||
_CCCL_IF_NOT_CONSTEVAL_DEFAULT
|
||||
{
|
||||
# if defined(_CCCL_BUILTIN_MEMSET)
|
||||
return reinterpret_cast<_Tp*>(_CCCL_BUILTIN_MEMSET(__ptr, __c, __n * sizeof(_Tp)));
|
||||
# else // ^^^ _CCCL_BUILTIN_MEMSET ^^^ / vvv !_CCCL_BUILTIN_MEMSET vvv
|
||||
NV_IF_TARGET(NV_IS_HOST, (return ::cuda::std::__cccl_memset_impl_host(__ptr, __c, __n);))
|
||||
# endif // ^^^ !_CCCL_BUILTIN_MEMSET ^^^
|
||||
}
|
||||
#endif // !_CCCL_TILE_COMPILATION()
|
||||
return ::cuda::std::__cccl_memset_impl_constexpr(__ptr, __c, __n);
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA_STD
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA_STD___STRING_CONSTEXPR_C_FUNCTIONS_H
|
||||
@@ -0,0 +1,314 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA_STD___STRING_HELPER_FUNCTIONS_H
|
||||
#define _CUDA_STD___STRING_HELPER_FUNCTIONS_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__algorithm/find.h>
|
||||
#include <cuda/std/__algorithm/find_end.h>
|
||||
#include <cuda/std/__algorithm/find_first_of.h>
|
||||
#include <cuda/std/__algorithm/min.h>
|
||||
#include <cuda/std/__cstddef/types.h>
|
||||
#include <cuda/std/__iterator/iterator_traits.h>
|
||||
#include <cuda/std/__string/char_traits.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA_STD
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT __cccl_str_find(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) noexcept
|
||||
{
|
||||
if (__pos >= __sz)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
|
||||
if (__r == nullptr)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
return static_cast<_SizeT>(__r - __p);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
_CCCL_API constexpr const _CharT*
|
||||
__cccl_search_substring(const _CharT* __first1, const _CharT* __last1, const _CharT* __first2, const _CharT* __last2)
|
||||
{
|
||||
// Take advantage of knowing source and pattern lengths.
|
||||
// Stop short when source is smaller than pattern.
|
||||
const ptrdiff_t __len2 = __last2 - __first2;
|
||||
if (__len2 == 0)
|
||||
{
|
||||
return __first1;
|
||||
}
|
||||
|
||||
ptrdiff_t __len1 = __last1 - __first1;
|
||||
if (__len1 < __len2)
|
||||
{
|
||||
return __last1;
|
||||
}
|
||||
|
||||
// First element of __first2 is loop invariant.
|
||||
_CharT __f2 = *__first2;
|
||||
while (true)
|
||||
{
|
||||
__len1 = __last1 - __first1;
|
||||
// Check whether __first1 still has at least __len2 bytes.
|
||||
if (__len1 < __len2)
|
||||
{
|
||||
// return __last1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Find __f2 the first byte matching in __first1.
|
||||
__first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
|
||||
if (__first1 == 0)
|
||||
{
|
||||
// return __last1;
|
||||
break;
|
||||
}
|
||||
|
||||
// It is faster to compare from the first byte of __first1 even if we
|
||||
// already know that it matches the first byte of __first2: this is because
|
||||
// __first2 is most likely aligned, as it is user's "pattern" string, and
|
||||
// __first1 + 1 is most likely not aligned, as the match is in the middle of
|
||||
// the string.
|
||||
if (_Traits::compare(__first1, __first2, __len2) == 0)
|
||||
{
|
||||
// return __first1;
|
||||
__last1 = __first1;
|
||||
break;
|
||||
}
|
||||
|
||||
++__first1;
|
||||
}
|
||||
return __last1;
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT
|
||||
__cccl_str_find(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) noexcept
|
||||
{
|
||||
if (__pos > __sz)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
|
||||
if (__n == 0) // There is nothing to search, just return __pos.
|
||||
{
|
||||
return __pos;
|
||||
}
|
||||
|
||||
const _CharT* __r = ::cuda::std::__cccl_search_substring<_CharT, _Traits>(__p + __pos, __p + __sz, __s, __s + __n);
|
||||
|
||||
if (__r == __p + __sz)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
return static_cast<_SizeT>(__r - __p);
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT __cccl_str_rfind(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) noexcept
|
||||
{
|
||||
if (__sz < 1)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
if (__pos < __sz)
|
||||
{
|
||||
++__pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
__pos = __sz;
|
||||
}
|
||||
_SizeT __result = __npos;
|
||||
for (const _CharT* __ps = __p + __pos; __ps != __p;)
|
||||
{
|
||||
if (_Traits::eq(*--__ps, __c))
|
||||
{
|
||||
__result = static_cast<_SizeT>(__ps - __p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT
|
||||
__cccl_str_rfind(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) noexcept
|
||||
{
|
||||
__pos = ::cuda::std::min(__pos, __sz);
|
||||
if (__n < __sz - __pos)
|
||||
{
|
||||
__pos += __n;
|
||||
}
|
||||
else
|
||||
{
|
||||
__pos = __sz;
|
||||
}
|
||||
const _CharT* __r = ::cuda::std::__find_end(
|
||||
__p, __p + __pos, __s, __s + __n, _Traits::eq, random_access_iterator_tag(), random_access_iterator_tag());
|
||||
if (__n > 0 && __r == __p + __pos)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
return static_cast<_SizeT>(__r - __p);
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT
|
||||
__cccl_str_find_first_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) noexcept
|
||||
{
|
||||
if (__pos >= __sz || __n == 0)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
const _CharT* __r = ::cuda::std::__find_first_of_ce(__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq);
|
||||
if (__r == __p + __sz)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
return static_cast<_SizeT>(__r - __p);
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT
|
||||
__cccl_str_find_last_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) noexcept
|
||||
{
|
||||
if (__n == 0)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
if (__pos < __sz)
|
||||
{
|
||||
++__pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
__pos = __sz;
|
||||
}
|
||||
_SizeT __result = __npos;
|
||||
for (const _CharT* __ps = __p + __pos; __ps != __p;)
|
||||
{
|
||||
if (_Traits::find(__s, __n, *--__ps) != nullptr)
|
||||
{
|
||||
__result = static_cast<_SizeT>(__ps - __p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT
|
||||
__cccl_str_find_first_not_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) noexcept
|
||||
{
|
||||
if (__pos >= __sz)
|
||||
{
|
||||
return __npos;
|
||||
}
|
||||
const _CharT* __pe = __p + __sz;
|
||||
_SizeT __result = __npos;
|
||||
for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
|
||||
{
|
||||
if (_Traits::find(__s, __n, *__ps) == nullptr)
|
||||
{
|
||||
__result = static_cast<_SizeT>(__ps - __p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT
|
||||
__cccl_str_find_first_not_of(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) noexcept
|
||||
{
|
||||
_SizeT __result = __npos;
|
||||
if (__pos < __sz)
|
||||
{
|
||||
const _CharT* __pe = __p + __sz;
|
||||
for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
|
||||
{
|
||||
if (!_Traits::eq(*__ps, __c))
|
||||
{
|
||||
__result = static_cast<_SizeT>(__ps - __p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT
|
||||
__cccl_str_find_last_not_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) noexcept
|
||||
{
|
||||
if (__pos < __sz)
|
||||
{
|
||||
++__pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
__pos = __sz;
|
||||
}
|
||||
|
||||
_SizeT __result = __npos;
|
||||
for (const _CharT* __ps = __p + __pos; __ps != __p;)
|
||||
{
|
||||
if (_Traits::find(__s, __n, *--__ps) == nullptr)
|
||||
{
|
||||
__result = static_cast<_SizeT>(__ps - __p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
|
||||
_CCCL_API constexpr _SizeT __cccl_str_find_last_not_of(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) noexcept
|
||||
{
|
||||
if (__pos < __sz)
|
||||
{
|
||||
++__pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
__pos = __sz;
|
||||
}
|
||||
_SizeT __result = __npos;
|
||||
for (const _CharT* __ps = __p + __pos; __ps != __p;)
|
||||
{
|
||||
if (!_Traits::eq(*--__ps, __c))
|
||||
{
|
||||
__result = static_cast<_SizeT>(__ps - __p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA_STD
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA_STD___STRING_HELPER_FUNCTIONS_H
|
||||
253
cccl_upstream/libcudacxx/include/cuda/std/__string/string_view.h
Normal file
253
cccl_upstream/libcudacxx/include/cuda/std/__string/string_view.h
Normal file
@@ -0,0 +1,253 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA_STD___STRING_STRING_VIEW_H
|
||||
#define _CUDA_STD___STRING_STRING_VIEW_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#if _LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
|
||||
# include <cuda/std/compare>
|
||||
#endif
|
||||
|
||||
#include <cuda/std/__exception/exception_macros.h>
|
||||
#include <cuda/std/__host_stdlib/stdexcept>
|
||||
#include <cuda/std/__string/char_traits.h>
|
||||
#include <cuda/std/__type_traits/is_constant_evaluated.h>
|
||||
#include <cuda/std/cstddef>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA_STD
|
||||
|
||||
struct __string_view
|
||||
{
|
||||
_CCCL_API constexpr __string_view(char const* __str, size_t __len) noexcept
|
||||
: __str_(__str)
|
||||
, __len_(__len)
|
||||
{}
|
||||
|
||||
_CCCL_API constexpr explicit __string_view(char const* __str) noexcept
|
||||
: __str_(__str)
|
||||
, __len_(__strlen_(__str))
|
||||
{}
|
||||
|
||||
[[nodiscard]] _CCCL_API constexpr size_t size() const noexcept
|
||||
{
|
||||
return __len_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API constexpr char const* data() const noexcept
|
||||
{
|
||||
return __str_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API constexpr char const* begin() const noexcept
|
||||
{
|
||||
return __str_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API constexpr char const* end() const noexcept
|
||||
{
|
||||
return __str_ + __len_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API constexpr char const& operator[](ptrdiff_t __n) const noexcept
|
||||
{
|
||||
return __str_[__n];
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API constexpr __string_view substr(ptrdiff_t __start, ptrdiff_t __stop) const
|
||||
{
|
||||
return __string_view(__str_ + __check_offset(__start, __len_), __check_offset(__stop - __start, __len_));
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] _CCCL_API static constexpr int
|
||||
__compare_(char const* __s1, size_t __len1, char const* __s2, size_t __len2, size_t __n) noexcept
|
||||
{
|
||||
int __result = int(__len1) - int(__len2);
|
||||
if (__n)
|
||||
{
|
||||
for (;; ++__s1, ++__s2)
|
||||
{
|
||||
if (*__s1 < *__s2)
|
||||
{
|
||||
__result = -1;
|
||||
break;
|
||||
}
|
||||
if (*__s2 < *__s1)
|
||||
{
|
||||
__result = 1;
|
||||
break;
|
||||
}
|
||||
if (0 == --__n)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <bool _Forward>
|
||||
[[nodiscard]] _CCCL_API static constexpr ptrdiff_t
|
||||
__find(const char* __needle, size_t __needle_size, const char* __haystack_begin, const char* __haystack_end) noexcept
|
||||
{
|
||||
ptrdiff_t __result = -1;
|
||||
char const* __it = __haystack_begin;
|
||||
for (; __it != __haystack_end; (_Forward ? ++__it : --__it))
|
||||
{
|
||||
size_t __i = 0;
|
||||
for (; __i != __needle_size; ++__i)
|
||||
{
|
||||
if ((_Forward ? __it : __it - 1)[__i] != __needle[__i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (__i == __needle_size)
|
||||
{
|
||||
__result = _Forward ? __it - __haystack_begin : __it - __haystack_end - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
public:
|
||||
template <size_t _Np>
|
||||
[[nodiscard]] _CCCL_API constexpr ptrdiff_t find(const char (&__other)[_Np]) const noexcept
|
||||
{
|
||||
return ((_Np - 1) > __len_) ? -1 : __find<true>(__other, _Np - 1, __str_, __str_ + __len_ - (_Np - 1) + 1);
|
||||
}
|
||||
|
||||
template <size_t _Np>
|
||||
[[nodiscard]] _CCCL_API constexpr ptrdiff_t find_end(const char (&__other)[_Np]) const noexcept
|
||||
{
|
||||
return ((_Np - 1) > __len_) ? -1 : __find<false>(__other, _Np - 1, __str_ + __len_ - (_Np - 1) + 1, __str_);
|
||||
}
|
||||
|
||||
private:
|
||||
// This overload is selected when we're not in a constant evaluated context.
|
||||
// Compare the two strings' addresses as a shortcut, and fall back to a string
|
||||
// comparison it they are not equal.
|
||||
[[nodiscard]] _CCCL_API inline int __compare(__string_view const& __other, false_type) const noexcept
|
||||
{
|
||||
return __str_ == __other.__str_
|
||||
? int(__len_) - int(__other.__len_)
|
||||
: __compare_(__str_, __len_, __other.__str_, __other.__len_, (__min_) (__len_, __other.__len_));
|
||||
}
|
||||
|
||||
// This overload is selected when we're in a constant evaluated context. We
|
||||
// cannot compare the two strings' addresses so fall back to a string
|
||||
// comparison.
|
||||
[[nodiscard]] _CCCL_API constexpr int __compare(__string_view const& __other, true_type) const noexcept
|
||||
{
|
||||
return __compare_(__str_, __len_, __other.__str_, __other.__len_, (__min_) (__len_, __other.__len_));
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] _CCCL_API constexpr int compare(__string_view const& __other) const noexcept
|
||||
{
|
||||
// If we're in a constant evaluated context, we cannot compare the __str_
|
||||
// members for equality.
|
||||
return __compare(__other, bool_constant<__cccl_default_is_constant_evaluated()>());
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API friend constexpr bool
|
||||
operator==(__string_view const& __lhs, __string_view const& __rhs) noexcept
|
||||
{
|
||||
return __lhs.__len_ == __rhs.__len_ && __lhs.compare(__rhs) == 0;
|
||||
}
|
||||
|
||||
#if _LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
|
||||
|
||||
[[nodiscard]]
|
||||
_CCCL_API friend constexpr auto operator<=>(__string_view const& __lhs, __string_view const& __rhs) noexcept
|
||||
{
|
||||
return __lhs.compare(__rhs) <=> 0;
|
||||
}
|
||||
|
||||
#else // ^^^ _LIBCUDACXX_HAS_SPACESHIP_OPERATOR() ^^^ / vvv !_LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
|
||||
|
||||
[[nodiscard]]
|
||||
_CCCL_API friend constexpr bool operator!=(__string_view const& __lhs, __string_view const& __rhs) noexcept
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API friend constexpr bool
|
||||
operator<(__string_view const& __lhs, __string_view const& __rhs) noexcept
|
||||
{
|
||||
return __lhs.compare(__rhs) < 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API friend constexpr bool
|
||||
operator<=(__string_view const& __lhs, __string_view const& __rhs) noexcept
|
||||
{
|
||||
return __lhs.compare(__rhs) <= 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API friend constexpr bool
|
||||
operator>(__string_view const& __lhs, __string_view const& __rhs) noexcept
|
||||
{
|
||||
return __lhs.compare(__rhs) > 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API friend constexpr bool
|
||||
operator>=(__string_view const& __lhs, __string_view const& __rhs) noexcept
|
||||
{
|
||||
return __lhs.compare(__rhs) >= 0;
|
||||
}
|
||||
|
||||
#endif // !_LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
|
||||
|
||||
private:
|
||||
[[nodiscard]] _CCCL_API static constexpr size_t __min_(size_t __x, size_t __y) noexcept
|
||||
{
|
||||
return __x < __y ? __x : __y;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr size_t __strlen_0x_(char const* __str, size_t __len) noexcept
|
||||
{
|
||||
return *__str ? __strlen_0x_(__str + 1, __len + 1) : __len;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr size_t __strlen_(char const* __str) noexcept
|
||||
{
|
||||
return ::cuda::std::char_traits<char>::length(__str);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_API static constexpr size_t __check_offset(ptrdiff_t __diff, size_t __len)
|
||||
{
|
||||
if (__diff < 0 || static_cast<size_t>(__diff) > __len)
|
||||
{
|
||||
_CCCL_THROW(::std::out_of_range, "__string_view index out of range");
|
||||
}
|
||||
return static_cast<size_t>(__diff);
|
||||
}
|
||||
|
||||
char const* __str_;
|
||||
size_t __len_;
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA_STD
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA_STD___STRING_STRING_VIEW_H
|
||||
Reference in New Issue
Block a user