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
931 lines
34 KiB
Plaintext
931 lines
34 KiB
Plaintext
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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_VIEW
|
|
#define _CUDA_STD_STRING_VIEW
|
|
|
|
#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/min.h>
|
|
#include <cuda/std/__cstddef/types.h>
|
|
#include <cuda/std/__exception/exception_macros.h>
|
|
#include <cuda/std/__functional/hash.h>
|
|
#include <cuda/std/__functional/unary_function.h>
|
|
#include <cuda/std/__fwd/allocator.h>
|
|
#include <cuda/std/__fwd/char_traits.h>
|
|
#include <cuda/std/__fwd/string.h>
|
|
#include <cuda/std/__fwd/string_view.h>
|
|
#include <cuda/std/__host_stdlib/stdexcept>
|
|
#include <cuda/std/__iterator/access.h>
|
|
#include <cuda/std/__iterator/bounded_iter.h>
|
|
#include <cuda/std/__iterator/concepts.h>
|
|
#include <cuda/std/__iterator/data.h>
|
|
#include <cuda/std/__iterator/empty.h>
|
|
#include <cuda/std/__iterator/iterator_traits.h>
|
|
#include <cuda/std/__iterator/reverse_access.h>
|
|
#include <cuda/std/__iterator/reverse_iterator.h>
|
|
#include <cuda/std/__iterator/size.h>
|
|
#include <cuda/std/__memory/pointer_traits.h>
|
|
#include <cuda/std/__ranges/concepts.h>
|
|
#include <cuda/std/__ranges/data.h>
|
|
#include <cuda/std/__ranges/enable_borrowed_range.h>
|
|
#include <cuda/std/__ranges/enable_view.h>
|
|
#include <cuda/std/__ranges/size.h>
|
|
#include <cuda/std/__string/char_traits.h>
|
|
#include <cuda/std/__string/helper_functions.h>
|
|
#include <cuda/std/__type_traits/is_array.h>
|
|
#include <cuda/std/__type_traits/is_convertible.h>
|
|
#include <cuda/std/__type_traits/is_same.h>
|
|
#include <cuda/std/__type_traits/is_standard_layout.h>
|
|
#include <cuda/std/__type_traits/is_trivially_copyable.h>
|
|
#include <cuda/std/__type_traits/is_trivially_default_constructible.h>
|
|
#include <cuda/std/__type_traits/remove_cvref.h>
|
|
#include <cuda/std/__type_traits/type_identity.h>
|
|
#include <cuda/std/__utility/ctad_support.h>
|
|
#include <cuda/std/__utility/declval.h>
|
|
#include <cuda/std/limits>
|
|
#include <cuda/std/version>
|
|
|
|
// todo: find a way to get rid of these includes
|
|
#if _CCCL_HOSTED()
|
|
# include <string> // for std::basic_string operator<<
|
|
# if __cpp_lib_string_view >= 201606L
|
|
# include <string_view> // for std::basic_string_view operator<<
|
|
# endif // __cpp_lib_string_view >= 201606L
|
|
#endif // _CCCL_HOSTED()
|
|
|
|
#include <cuda/std/__cccl/prologue.h>
|
|
|
|
_CCCL_BEGIN_NAMESPACE_CUDA_STD
|
|
|
|
template <class _Range, class _CharT, class _Traits>
|
|
_CCCL_CONCEPT __cccl_has_basic_sv_conv_operator =
|
|
_CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits), remove_cvref_t<_Range>& __d)(
|
|
(__d.operator ::cuda::std::basic_string_view<_CharT, _Traits>()));
|
|
|
|
template <class _Range, class _CharT, class _Traits>
|
|
_CCCL_CONCEPT __cccl_basic_sv_compatible_range_check_traits = _CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits)) //
|
|
( //
|
|
typename(typename _Range::traits_type), //
|
|
requires(is_same_v<typename _Range::traits_type, _Traits>) //
|
|
);
|
|
|
|
template <class _Range, class _CharT, class _Traits>
|
|
_CCCL_CONCEPT __cccl_basic_sv_compatible_range_check_traits_std_ext =
|
|
#if _CCCL_HOSTED()
|
|
_CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits)) //
|
|
( //
|
|
typename(typename _Range::traits_type), //
|
|
requires(is_same_v<typename _Range::traits_type, ::std::char_traits<_CharT>>), //
|
|
requires(is_same_v<_Traits, ::cuda::std::char_traits<_CharT>>) //
|
|
);
|
|
#else // ^^^ _CCCL_HOSTED() ^^^ / vvv _CCCL_FREESTANDING() vvv
|
|
true;
|
|
#endif // ^^^ _CCCL_FREESTANDING() ^^^
|
|
|
|
template <class _Range, class _CharT, class _Traits>
|
|
_CCCL_CONCEPT __cccl_basic_sv_compatible_range = _CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits)) //
|
|
( //
|
|
requires(::cuda::std::ranges::contiguous_range<_Range>), //
|
|
requires(::cuda::std::ranges::sized_range<_Range>), //
|
|
requires(is_same_v<::cuda::std::ranges::range_value_t<_Range>, _CharT>), //
|
|
requires(!(__is_cuda_std_basic_string_view_v<remove_cvref_t<_Range>>
|
|
&& __cccl_basic_sv_compatible_range_check_traits<_Range, _CharT, _Traits>) ), //
|
|
requires(!is_convertible_v<_Range, const _CharT*>), //
|
|
requires(!__cccl_has_basic_sv_conv_operator<_Range, _CharT, _Traits>), //
|
|
requires(!(__is_std_basic_string_v<remove_cvref_t<_Range>>
|
|
&& (__cccl_basic_sv_compatible_range_check_traits<_Range, _CharT, _Traits>
|
|
|| __cccl_basic_sv_compatible_range_check_traits_std_ext<_Range, _CharT, _Traits>) )), //
|
|
requires(!(__is_std_basic_string_view_v<remove_cvref_t<_Range>>
|
|
&& (__cccl_basic_sv_compatible_range_check_traits<_Range, _CharT, _Traits>
|
|
|| __cccl_basic_sv_compatible_range_check_traits_std_ext<_Range, _CharT, _Traits>) )) //
|
|
);
|
|
|
|
template <class _Traits, class _HostTraits>
|
|
_CCCL_CONCEPT __cccl_basic_sv_is_std_to_cuda_std_char_traits = _CCCL_REQUIRES_EXPR((_Traits, _HostTraits)) //
|
|
( //
|
|
requires(__is_cuda_std_char_traits_v<_Traits>), //
|
|
requires(__is_std_char_traits_v<_HostTraits>) //
|
|
);
|
|
|
|
template <class _CharT, class _Traits>
|
|
class _CCCL_TYPE_VISIBILITY_DEFAULT basic_string_view
|
|
{
|
|
public:
|
|
using traits_type = _Traits;
|
|
using value_type = _CharT;
|
|
using pointer = _CharT*;
|
|
using const_pointer = const _CharT*;
|
|
using reference = _CharT&;
|
|
using const_reference = const _CharT&;
|
|
using const_iterator = const_pointer;
|
|
using iterator = const_iterator;
|
|
using const_reverse_iterator = ::cuda::std::reverse_iterator<const_iterator>;
|
|
using reverse_iterator = const_reverse_iterator;
|
|
using size_type = size_t;
|
|
using difference_type = ptrdiff_t;
|
|
|
|
static constexpr const size_type npos = static_cast<size_type>(-1);
|
|
|
|
static_assert(!is_array_v<value_type>, "character type of basic_string_view must not be an array");
|
|
static_assert(is_standard_layout_v<value_type>, "character type of basic_string_view must be standard-layout");
|
|
static_assert(is_trivially_default_constructible_v<value_type>,
|
|
"character type of basic_string_view must be trivially default constructible");
|
|
static_assert(is_trivially_copyable_v<value_type>, "character type of basic_string_view must be trivially copyable");
|
|
static_assert(is_same_v<_CharT, typename traits_type::char_type>,
|
|
"traits_type::char_type must be the same type as CharT");
|
|
|
|
_CCCL_API constexpr basic_string_view() noexcept
|
|
: __data_{}
|
|
, __size_{}
|
|
{}
|
|
|
|
_CCCL_HIDE_FROM_ABI basic_string_view(const basic_string_view&) noexcept = default;
|
|
|
|
_CCCL_HIDE_FROM_ABI basic_string_view& operator=(const basic_string_view&) noexcept = default;
|
|
|
|
_CCCL_API constexpr basic_string_view(const _CharT* __s) noexcept
|
|
: __data_{__s}
|
|
, __size_{_Traits::length(__s)}
|
|
{}
|
|
|
|
basic_string_view(nullptr_t) = delete;
|
|
|
|
_CCCL_API constexpr basic_string_view(const _CharT* __s, size_type __len) noexcept
|
|
: __data_{__s}
|
|
, __size_{__len}
|
|
{
|
|
// Allocations must fit in `difference_type` for pointer arithmetic to work. If `__len` exceeds it, the input
|
|
// range could not have been valid. Most likely the caller underflowed some arithmetic and inadvertently
|
|
// passed in a negative length.
|
|
_CCCL_ASSERT(__len <= static_cast<size_type>(numeric_limits<difference_type>::max()),
|
|
"string_view::string_view(_CharT *, size_t): length does not fit in difference_type");
|
|
_CCCL_ASSERT(__len == 0 || __s != nullptr, "string_view::string_view(_CharT *, size_t): received nullptr");
|
|
}
|
|
|
|
_CCCL_EXEC_CHECK_DISABLE
|
|
_CCCL_TEMPLATE(class _It, class _End)
|
|
_CCCL_REQUIRES(contiguous_iterator<_It> _CCCL_AND sized_sentinel_for<_End, _It> _CCCL_AND
|
|
is_same_v<iter_value_t<_It>, _CharT> _CCCL_AND(!is_convertible_v<_End, size_type>))
|
|
_CCCL_API constexpr basic_string_view(_It __begin, _End __end)
|
|
: __data_{::cuda::std::to_address(__begin)}
|
|
, __size_{static_cast<size_type>(__end - __begin)}
|
|
{
|
|
_CCCL_ASSERT((__end - __begin) >= 0, "string_view::string_view(iterator, sentinel) received invalid range");
|
|
}
|
|
|
|
#if _CCCL_HOSTED()
|
|
_CCCL_TEMPLATE(class _Traits2, class _Alloc)
|
|
_CCCL_REQUIRES(__cccl_basic_sv_is_std_to_cuda_std_char_traits<_Traits, _Traits2>)
|
|
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string<_CharT, _Traits2, _Alloc>& __sv) noexcept
|
|
: __data_{__sv.data()}
|
|
, __size_{__sv.size()}
|
|
{}
|
|
|
|
_CCCL_TEMPLATE(class _Traits2, class _Alloc)
|
|
_CCCL_REQUIRES(is_same_v<_Traits, _Traits2>)
|
|
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string<_CharT, _Traits2, _Alloc>& __sv) noexcept
|
|
: __data_{__sv.data()}
|
|
, __size_{__sv.size()}
|
|
{}
|
|
#endif // _CCCL_HOSTED()
|
|
|
|
#if __cpp_lib_string_view >= 201606L
|
|
_CCCL_TEMPLATE(class _Traits2)
|
|
_CCCL_REQUIRES(__cccl_basic_sv_is_std_to_cuda_std_char_traits<_Traits, _Traits2>)
|
|
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string_view<_CharT, _Traits2>& __s) noexcept
|
|
: __data_{__s.data()}
|
|
, __size_{__s.size()}
|
|
{}
|
|
|
|
_CCCL_TEMPLATE(class _Traits2)
|
|
_CCCL_REQUIRES(is_same_v<_Traits, _Traits2>)
|
|
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string_view<_CharT, _Traits2>& __s) noexcept
|
|
: __data_{__s.data()}
|
|
, __size_{__s.size()}
|
|
{}
|
|
#endif // __cpp_lib_string_view >= 201606L
|
|
|
|
// NOLINTBEGIN(bugprone-forwarding-reference-overload)
|
|
_CCCL_TEMPLATE(class _Range)
|
|
_CCCL_REQUIRES(__cccl_basic_sv_compatible_range<_Range, _CharT, _Traits>)
|
|
_CCCL_API explicit constexpr basic_string_view(_Range&& __r)
|
|
: __data_{::cuda::std::ranges::__data_cpo{}(__r)}
|
|
, __size_{::cuda::std::ranges::__size_cpo{}(__r)}
|
|
{}
|
|
// NOLINTEND(bugprone-forwarding-reference-overload)
|
|
|
|
// msvc has problems with constructing a string view from another string view using the from ranges constructor,
|
|
// so we define the constructor ourselves
|
|
#if _CCCL_COMPILER(MSVC)
|
|
_CCCL_TEMPLATE(class _OtherTraits)
|
|
_CCCL_REQUIRES((!is_same_v<_Traits, _OtherTraits>) )
|
|
_CCCL_API explicit constexpr basic_string_view(const basic_string_view<_CharT, _OtherTraits>& __other)
|
|
: __data_{__other.data()}
|
|
, __size_{__other.size()}
|
|
{}
|
|
#endif // _CCCL_COMPILER(MSVC)
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_iterator begin() const noexcept
|
|
{
|
|
return const_iterator{__data_};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_iterator end() const noexcept
|
|
{
|
|
return const_iterator{__data_ + __size_};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_iterator cbegin() const noexcept
|
|
{
|
|
return const_iterator{__data_};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_iterator cend() const noexcept
|
|
{
|
|
return const_iterator{__data_ + __size_};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reverse_iterator rbegin() const noexcept
|
|
{
|
|
return const_reverse_iterator{cend()};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reverse_iterator rend() const noexcept
|
|
{
|
|
return const_reverse_iterator{cbegin()};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reverse_iterator crbegin() const noexcept
|
|
{
|
|
return const_reverse_iterator{cend()};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reverse_iterator crend() const noexcept
|
|
{
|
|
return const_reverse_iterator{cbegin()};
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type size() const noexcept
|
|
{
|
|
return __size_;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type length() const noexcept
|
|
{
|
|
return __size_;
|
|
}
|
|
|
|
// Workaround for cudafe++ < 13.1 + gcc < 13 replacing `numeric_limits<size_t>` with
|
|
// `numeric_limits<conditional<is_void_v<void>, __common_type2_imp<uint64_t, uint64_t>::type, void>::type>`
|
|
template <class _SizeType = size_type>
|
|
[[nodiscard]] _CCCL_API constexpr size_type max_size() const noexcept
|
|
{
|
|
return numeric_limits<_SizeType>::max() / sizeof(value_type);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool empty() const noexcept
|
|
{
|
|
return __size_ == 0;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reference operator[](size_type __pos) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__pos < __size_, "string_view[] index out of bounds");
|
|
return __data_[__pos];
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reference at(size_type __pos) const
|
|
{
|
|
if (__pos >= __size_)
|
|
{
|
|
_CCCL_THROW(::std::out_of_range, "string_view::at");
|
|
}
|
|
return __data_[__pos];
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reference front() const noexcept
|
|
{
|
|
_CCCL_ASSERT(__size_ > 0, "string_view::front(): string is empty");
|
|
return __data_[0];
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_reference back() const noexcept
|
|
{
|
|
_CCCL_ASSERT(__size_ > 0, "string_view::back(): string is empty");
|
|
return __data_[__size_ - 1];
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr const_pointer data() const noexcept
|
|
{
|
|
return __data_;
|
|
}
|
|
|
|
_CCCL_API constexpr void remove_prefix(size_type __n) noexcept
|
|
{
|
|
_CCCL_ASSERT(__n <= __size_, "remove_prefix() can't remove more than size()");
|
|
__data_ += __n;
|
|
__size_ -= __n;
|
|
}
|
|
|
|
_CCCL_API constexpr void remove_suffix(size_type __n) noexcept
|
|
{
|
|
_CCCL_ASSERT(__n <= __size_, "remove_suffix() can't remove more than size()");
|
|
__size_ -= __n;
|
|
}
|
|
|
|
_CCCL_API constexpr void swap(basic_string_view& __other) noexcept
|
|
{
|
|
const value_type* __p = __data_;
|
|
__data_ = __other.__data_;
|
|
__other.__data_ = __p;
|
|
|
|
size_type __sz = __size_;
|
|
__size_ = __other.__size_;
|
|
__other.__size_ = __sz;
|
|
}
|
|
|
|
_CCCL_API constexpr size_type copy(_CharT* __s, size_type __n, size_type __pos = 0) const
|
|
{
|
|
if (__pos > __size_)
|
|
{
|
|
_CCCL_THROW(::std::out_of_range, "string_view::copy");
|
|
}
|
|
const auto __rlen = ::cuda::std::min(__n, __size_ - __pos);
|
|
_Traits::copy(__s, __data_ + __pos, __rlen);
|
|
return __rlen;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr basic_string_view substr(size_type __pos = 0, size_type __n = npos) const
|
|
{
|
|
// Use the `__assume_valid` form of the constructor to avoid an unnecessary check. Any substring of a view is a
|
|
// valid view. In particular, `size()` is known to be smaller than `numeric_limits<difference_type>::max()`, so the
|
|
// new size is also smaller. See also https://github.com/llvm/llvm-project/issues/91634.
|
|
if (__pos > __size_)
|
|
{
|
|
_CCCL_THROW(::std::out_of_range, "string_view::substr");
|
|
}
|
|
return basic_string_view{__assume_valid{}, __data_ + __pos, ::cuda::std::min(__n, __size_ - __pos)};
|
|
}
|
|
|
|
// compare
|
|
|
|
[[nodiscard]] _CCCL_API constexpr int compare(basic_string_view __sv) const noexcept
|
|
{
|
|
const auto __rlen = ::cuda::std::min(__size_, __sv.__size_);
|
|
int __retval = _Traits::compare(__data_, __sv.__data_, __rlen);
|
|
if (__retval == 0) // first __rlen chars matched
|
|
{
|
|
__retval = (__size_ == __sv.__size_) ? 0 : ((__size_ < __sv.__size_) ? -1 : 1);
|
|
}
|
|
return __retval;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __sv) const
|
|
{
|
|
return substr(__pos1, __n1).compare(__sv);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr int
|
|
compare(size_type __pos1, size_type __n1, basic_string_view __sv, size_type __pos2, size_type __n2) const
|
|
{
|
|
return substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr int compare(const _CharT* __s) const noexcept
|
|
{
|
|
return compare(basic_string_view{__s});
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr int compare(size_type __pos1, size_type __n1, const _CharT* __s) const
|
|
{
|
|
return substr(__pos1, __n1).compare(basic_string_view{__s});
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr int
|
|
compare(size_type __pos1, size_type __n1, const _CharT* __s, size_type __n2) const
|
|
{
|
|
return substr(__pos1, __n1).compare(basic_string_view{__s, __n2});
|
|
}
|
|
|
|
// find
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find(basic_string_view __s, size_type __pos = 0) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s.__data_, __pos, __s.__size_);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find(_CharT __c, size_type __pos = 0) const noexcept
|
|
{
|
|
return ::cuda::std::__cccl_str_find<value_type, size_type, traits_type, npos>(__data_, __size_, __c, __pos);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find(const _CharT* __s, size_type __pos, size_type __n) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find<value_type, size_type, traits_type, npos>(__data_, __size_, __s, __pos, __n);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find(const _CharT* __s, size_type __pos = 0) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s != nullptr, "string_view::find(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
// rfind
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type rfind(basic_string_view __s, size_type __pos = npos) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find(): received nullptr");
|
|
return ::cuda::std::__cccl_str_rfind<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s.__data_, __pos, __s.__size_);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type rfind(_CharT __c, size_type __pos = npos) const noexcept
|
|
{
|
|
return ::cuda::std::__cccl_str_rfind<value_type, size_type, traits_type, npos>(__data_, __size_, __c, __pos);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr");
|
|
return ::cuda::std::__cccl_str_rfind<value_type, size_type, traits_type, npos>(__data_, __size_, __s, __pos, __n);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type rfind(const _CharT* __s, size_type __pos = npos) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s != nullptr, "string_view::rfind(): received nullptr");
|
|
return ::cuda::std::__cccl_str_rfind<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
// find_first_of
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_first_of(basic_string_view __s, size_type __pos = 0) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_first_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_first_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s.__data_, __pos, __s.__size_);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_first_of(_CharT __c, size_type __pos = 0) const noexcept
|
|
{
|
|
return find(__c, __pos);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type
|
|
find_first_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_first_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, __n);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_first_of(const _CharT* __s, size_type __pos = 0) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s != nullptr, "string_view::find_first_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_first_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
// find_last_of
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_last_of(basic_string_view __s, size_type __pos = npos) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_last_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_last_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s.__data_, __pos, __s.__size_);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_last_of(_CharT __c, size_type __pos = npos) const noexcept
|
|
{
|
|
return rfind(__c, __pos);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type
|
|
find_last_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_last_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, __n);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_last_of(const _CharT* __s, size_type __pos = npos) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s != nullptr, "string_view::find_last_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_last_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
// find_first_not_of
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type
|
|
find_first_not_of(basic_string_view __s, size_type __pos = 0) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_first_not_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_first_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s.__data_, __pos, __s.__size_);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept
|
|
{
|
|
return ::cuda::std::__cccl_str_find_first_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __c, __pos);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type
|
|
find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_first_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, __n);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s != nullptr, "string_view::find_first_not_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_first_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
// find_last_not_of
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type
|
|
find_last_not_of(basic_string_view __s, size_type __pos = npos) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_last_not_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_last_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s.__data_, __pos, __s.__size_);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept
|
|
{
|
|
return ::cuda::std::__cccl_str_find_last_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __c, __pos);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type
|
|
find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_last_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, __n);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr size_type find_last_not_of(const _CharT* __s, size_type __pos = npos) const noexcept
|
|
{
|
|
_CCCL_ASSERT(__s != nullptr, "string_view::find_last_not_of(): received nullptr");
|
|
return ::cuda::std::__cccl_str_find_last_not_of<value_type, size_type, traits_type, npos>(
|
|
__data_, __size_, __s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
// starts_with
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool starts_with(basic_string_view __s) const noexcept
|
|
{
|
|
return (__size_ >= __s.__size_) && compare(0, __s.__size_, __s) == 0;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool starts_with(value_type __c) const noexcept
|
|
{
|
|
return (__size_ > 0) && _Traits::eq(front(), __c);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool starts_with(const value_type* __s) const noexcept
|
|
{
|
|
return starts_with(basic_string_view{__s});
|
|
}
|
|
|
|
// ends_with
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool ends_with(basic_string_view __s) const noexcept
|
|
{
|
|
return (__size_ >= __s.__size_) && compare(__size_ - __s.__size_, npos, __s) == 0;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool ends_with(value_type __c) const noexcept
|
|
{
|
|
return (__size_ > 0) && _Traits::eq(back(), __c);
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool ends_with(const value_type* __s) const noexcept
|
|
{
|
|
return ends_with(basic_string_view{__s});
|
|
}
|
|
|
|
// contains
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool contains(basic_string_view __sv) const noexcept
|
|
{
|
|
return find(__sv) != npos;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool contains(value_type __c) const noexcept
|
|
{
|
|
return find(__c) != npos;
|
|
}
|
|
|
|
[[nodiscard]] _CCCL_API constexpr bool contains(const value_type* __s) const noexcept
|
|
{
|
|
return find(__s) != npos;
|
|
}
|
|
|
|
// The dummy default template parameters are used to work around a MSVC issue with mangling, see VSO-409326 for
|
|
// details. This applies to the other sufficient overloads below for the other comparison operators.
|
|
|
|
// operator ==
|
|
|
|
[[nodiscard]] _CCCL_API friend constexpr bool operator==(basic_string_view __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
if (__lhs.__size_ != __rhs.__size_)
|
|
{
|
|
return false;
|
|
}
|
|
return __lhs.compare(__rhs) == 0;
|
|
}
|
|
|
|
template <int = 1>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator==(basic_string_view __lhs, type_identity_t<basic_string_view> __rhs) noexcept
|
|
{
|
|
if (__lhs.__size_ != __rhs.__size_)
|
|
{
|
|
return false;
|
|
}
|
|
return __lhs.compare(__rhs) == 0;
|
|
}
|
|
|
|
template <unsigned = 2>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator==(type_identity_t<basic_string_view> __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs == __rhs;
|
|
}
|
|
|
|
// operator !=
|
|
|
|
[[nodiscard]] _CCCL_API friend constexpr bool operator!=(basic_string_view __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return !(__lhs == __rhs);
|
|
}
|
|
|
|
template <int = 1>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator!=(basic_string_view __lhs, type_identity_t<basic_string_view> __rhs) noexcept
|
|
{
|
|
return !(__lhs == __rhs);
|
|
}
|
|
|
|
template <unsigned = 2>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator!=(type_identity_t<basic_string_view> __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return !(__lhs == __rhs);
|
|
}
|
|
|
|
// operator <
|
|
|
|
[[nodiscard]] _CCCL_API friend constexpr bool operator<(basic_string_view __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) < 0;
|
|
}
|
|
|
|
template <int = 1>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator<(basic_string_view __lhs, type_identity_t<basic_string_view> __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) < 0;
|
|
}
|
|
|
|
template <unsigned = 2>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator<(type_identity_t<basic_string_view> __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) < 0;
|
|
}
|
|
|
|
// operator >
|
|
|
|
[[nodiscard]] _CCCL_API friend constexpr bool operator>(basic_string_view __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) > 0;
|
|
}
|
|
|
|
template <int = 1>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator>(basic_string_view __lhs, type_identity_t<basic_string_view> __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) > 0;
|
|
}
|
|
|
|
template <unsigned = 2>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator>(type_identity_t<basic_string_view> __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) > 0;
|
|
}
|
|
|
|
// operator <=
|
|
|
|
[[nodiscard]] _CCCL_API friend constexpr bool operator<=(basic_string_view __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) <= 0;
|
|
}
|
|
|
|
template <int = 1>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator<=(basic_string_view __lhs, type_identity_t<basic_string_view> __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) <= 0;
|
|
}
|
|
|
|
template <unsigned = 2>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator<=(type_identity_t<basic_string_view> __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) <= 0;
|
|
}
|
|
|
|
// operator >=
|
|
|
|
[[nodiscard]] _CCCL_API friend constexpr bool operator>=(basic_string_view __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) >= 0;
|
|
}
|
|
|
|
template <int = 1>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator>=(basic_string_view __lhs, type_identity_t<basic_string_view> __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) >= 0;
|
|
}
|
|
|
|
template <unsigned = 2>
|
|
[[nodiscard]] _CCCL_API friend constexpr bool
|
|
operator>=(type_identity_t<basic_string_view> __lhs, basic_string_view __rhs) noexcept
|
|
{
|
|
return __lhs.compare(__rhs) >= 0;
|
|
}
|
|
|
|
#if __cpp_lib_string_view >= 201606L
|
|
_CCCL_TEMPLATE(class _Traits2 = _Traits)
|
|
_CCCL_REQUIRES(is_same_v<_Traits2, char_traits<_CharT>>)
|
|
_CCCL_HOST_API constexpr operator ::std::basic_string_view<_CharT>() const noexcept
|
|
{
|
|
return ::std::basic_string_view<_CharT>{__data_, __size_};
|
|
}
|
|
|
|
_CCCL_HOST_API constexpr operator ::std::basic_string_view<_CharT, _Traits>() const noexcept
|
|
{
|
|
return ::std::basic_string_view<_CharT, _Traits>{__data_, __size_};
|
|
}
|
|
#endif // ^^^ __cpp_lib_string_view >= 201606L ^^^
|
|
|
|
private:
|
|
enum class __assume_valid
|
|
{
|
|
};
|
|
|
|
// This is the same as the pointer and length constructor, but without the additional hardening checks. It is intended
|
|
// for use within the class, when the class invariants already guarantee the resulting object is valid. The compiler
|
|
// usually cannot eliminate the redundant checks because it does not know class invariants.
|
|
_CCCL_API constexpr basic_string_view(__assume_valid, const _CharT* __s, size_type __len) noexcept
|
|
: __data_{__s}
|
|
, __size_{__len}
|
|
{}
|
|
|
|
const value_type* __data_;
|
|
size_type __size_;
|
|
};
|
|
|
|
_CCCL_CTAD_SUPPORTED_FOR_TYPE(basic_string_view);
|
|
|
|
_CCCL_TEMPLATE(class _It, class _End)
|
|
_CCCL_REQUIRES(contiguous_iterator<_It> _CCCL_AND sized_sentinel_for<_End, _It>)
|
|
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>;
|
|
|
|
_CCCL_TEMPLATE(class _Range)
|
|
_CCCL_REQUIRES(::cuda::std::ranges::contiguous_range<_Range>)
|
|
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES basic_string_view(_Range&&)
|
|
-> basic_string_view<::cuda::std::ranges::range_value_t<_Range>>;
|
|
|
|
#if _CCCL_HOSTED()
|
|
template <class _CharT, class _Alloc>
|
|
basic_string_view(::std::basic_string<_CharT, ::std::char_traits<_CharT>, _Alloc>) -> basic_string_view<_CharT>;
|
|
|
|
template <class _CharT, class _Traits, class _Alloc>
|
|
basic_string_view(::std::basic_string<_CharT, _Traits, _Alloc>) -> basic_string_view<_CharT, _Traits>;
|
|
#endif // _CCCL_HOSTED()
|
|
|
|
#if __cpp_lib_string_view >= 201606L
|
|
template <class _CharT>
|
|
basic_string_view(::std::basic_string_view<_CharT>) -> basic_string_view<_CharT>;
|
|
|
|
template <class _CharT, class _Traits>
|
|
basic_string_view(::std::basic_string_view<_CharT, _Traits>) -> basic_string_view<_CharT, _Traits>;
|
|
#endif // __cpp_lib_string_view >= 201606L
|
|
|
|
// operator <<
|
|
|
|
#if _CCCL_HOSTED()
|
|
template <class _CharT>
|
|
_CCCL_HOST_API ::std::basic_ostream<_CharT>&
|
|
operator<<(::std::basic_ostream<_CharT>& __os, basic_string_view<_CharT> __str)
|
|
{
|
|
# if __cpp_lib_string_view >= 201606L
|
|
return __os << ::std::basic_string_view<_CharT, ::std::char_traits<_CharT>>{__str};
|
|
# else // ^^^ __cpp_lib_string_view >= 201606L ^^^ / vvv __cpp_lib_string_view < 201606L vvv
|
|
return __os
|
|
<< ::std::basic_string<_CharT, ::std::char_traits<_CharT>, ::std::allocator<_CharT>>{__str.data(), __str.size()};
|
|
# endif // ^^^ __cpp_lib_string_view < 201606L ^^^
|
|
}
|
|
|
|
template <class _CharT, class _Traits>
|
|
_CCCL_HOST_API ::std::basic_ostream<_CharT, _Traits>&
|
|
operator<<(::std::basic_ostream<_CharT, _Traits>& __os, basic_string_view<_CharT, _Traits> __str)
|
|
{
|
|
# if __cpp_lib_string_view >= 201606L
|
|
return __os << ::std::basic_string_view<_CharT, _Traits>{__str};
|
|
# else // ^^^ __cpp_lib_string_view >= 201606L ^^^ / vvv __cpp_lib_string_view < 201606L vvv
|
|
return __os << ::std::basic_string<_CharT, _Traits, ::std::allocator<_CharT>>{__str.data(), __str.size()};
|
|
# endif // ^^^ __cpp_lib_string_view < 201606L ^^^
|
|
}
|
|
#endif // _CCCL_HOSTED()
|
|
|
|
// literals
|
|
|
|
_CCCL_DIAG_PUSH
|
|
_CCCL_DIAG_SUPPRESS_GCC("-Wliteral-suffix")
|
|
_CCCL_DIAG_SUPPRESS_CLANG("-Wuser-defined-literals")
|
|
_CCCL_DIAG_SUPPRESS_MSVC(4455)
|
|
|
|
inline namespace literals
|
|
{
|
|
inline namespace string_view_literals
|
|
{
|
|
_CCCL_API constexpr basic_string_view<char> operator""sv(const char* __str, size_t __len) noexcept
|
|
{
|
|
return basic_string_view<char>{__str, __len};
|
|
}
|
|
|
|
#if _CCCL_HAS_WCHAR_T()
|
|
_CCCL_API constexpr basic_string_view<wchar_t> operator""sv(const wchar_t* __str, size_t __len) noexcept
|
|
{
|
|
return basic_string_view<wchar_t>{__str, __len};
|
|
}
|
|
#endif // _CCCL_HAS_WCHAR_T()
|
|
|
|
#if _CCCL_HAS_CHAR8_T()
|
|
_CCCL_API constexpr basic_string_view<char8_t> operator""sv(const char8_t* __str, size_t __len) noexcept
|
|
{
|
|
return basic_string_view<char8_t>{__str, __len};
|
|
}
|
|
#endif // _CCCL_HAS_CHAR8_T()
|
|
|
|
_CCCL_API constexpr basic_string_view<char16_t> operator""sv(const char16_t* __str, size_t __len) noexcept
|
|
{
|
|
return basic_string_view<char16_t>{__str, __len};
|
|
}
|
|
|
|
_CCCL_API constexpr basic_string_view<char32_t> operator""sv(const char32_t* __str, size_t __len) noexcept
|
|
{
|
|
return basic_string_view<char32_t>{__str, __len};
|
|
}
|
|
} // namespace string_view_literals
|
|
} // namespace literals
|
|
|
|
_CCCL_DIAG_POP
|
|
|
|
_CCCL_END_NAMESPACE_CUDA_STD
|
|
|
|
_CCCL_BEGIN_NAMESPACE_CUDA_STD_RANGES
|
|
|
|
template <class _CharT, class _Traits>
|
|
inline constexpr bool enable_view<::cuda::std::basic_string_view<_CharT, _Traits>> = true;
|
|
|
|
template <class _CharT, class _Traits>
|
|
inline constexpr bool enable_borrowed_range<::cuda::std::basic_string_view<_CharT, _Traits>> = true;
|
|
|
|
_CCCL_END_NAMESPACE_CUDA_STD_RANGES
|
|
|
|
#include <cuda/std/__cccl/epilogue.h>
|
|
|
|
#endif // _CUDA_STD_STRING_VIEW
|