Skip to content

Commit

Permalink
Merge pull request #703 from trcrsired/master
Browse files Browse the repository at this point in the history
add cstring_view
  • Loading branch information
trcrsired authored Apr 11, 2024
2 parents d920bc1 + 72392d0 commit 90d5f1f
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 11 deletions.
54 changes: 54 additions & 0 deletions include/fast_io_dsal/cstring_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once
#undef min
#undef max

#if !defined(__cplusplus)
#error "You must be using a C++ compiler"
#endif

#if !defined(__cplusplus)
#error "You must be using a C++ compiler"
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
#pragma warning(disable : 4464)
#pragma warning(disable : 4514)
#pragma warning(disable : 4623)
#pragma warning(disable : 4626)
#pragma warning(disable : 4668)
#pragma warning(disable : 4710)
#pragma warning(disable : 4820)
#pragma warning(disable : 5027)
#pragma warning(disable : 5045)
#include <cstring>
#endif

#include "string_view.h"
#include "impl/cstring_view.h"

namespace fast_io
{

using ::fast_io::containers::null_terminated;
using ::fast_io::containers::null_terminated_t;

using cstring_view = ::fast_io::containers::basic_cstring_view<char>;
using wcstring_view = ::fast_io::containers::basic_cstring_view<wchar_t>;
using u8cstring_view = ::fast_io::containers::basic_cstring_view<char8_t>;
using u16cstring_view = ::fast_io::containers::basic_cstring_view<char16_t>;
using u32cstring_view = ::fast_io::containers::basic_cstring_view<char32_t>;

namespace tlc
{
using cstring_view = ::fast_io::containers::basic_cstring_view<char>;
using wcstring_view = ::fast_io::containers::basic_cstring_view<wchar_t>;
using u8cstring_view = ::fast_io::containers::basic_cstring_view<char8_t>;
using u16cstring_view = ::fast_io::containers::basic_cstring_view<char16_t>;
using u32cstring_view = ::fast_io::containers::basic_cstring_view<char32_t>;
} // namespace tlc

} // namespace fast_io

#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif
187 changes: 187 additions & 0 deletions include/fast_io_dsal/impl/cstring_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#pragma once

namespace fast_io::containers
{

struct null_terminated_t
{
explicit inline constexpr null_terminated_t() noexcept = default;
};

inline constexpr null_terminated_t null_terminated{};

template <::std::integral char_type>
class basic_cstring_view : private ::fast_io::containers::basic_string_view<char_type>
{
public:
using string_view_type = ::fast_io::containers::basic_string_view<char_type>;
using typename string_view_type::value_type;
using typename string_view_type::size_type;
using typename string_view_type::difference_type;
using typename string_view_type::reference;
using typename string_view_type::const_reference;
using typename string_view_type::const_pointer;
using typename string_view_type::pointer;
using typename string_view_type::const_iterator;
using typename string_view_type::iterator;
using typename string_view_type::const_reverse_iterator;
using typename string_view_type::reverse_iterator;
using string_view_type::ptr;
using string_view_type::n;

constexpr basic_cstring_view() noexcept = default;

constexpr basic_cstring_view(::std::nullptr_t) = delete;

explicit constexpr basic_cstring_view(::fast_io::containers::null_terminated_t, const_pointer p, size_type s) noexcept
: string_view_type(p, s)
{}
template <::std::size_t N>
constexpr basic_cstring_view(char_type const (&buffer)[N]) noexcept
: string_view_type(buffer)
{
constexpr ::std::size_t nm1{N - 1u};
if (buffer[nm1]) [[unlikely]]
{
::fast_io::fast_terminate();
}
}

explicit constexpr basic_cstring_view(::fast_io::containers::null_terminated_t, string_view_type stvw) noexcept
: string_view_type(stvw)
{
}

template <::std::ranges::contiguous_range rg>
requires(::std::constructible_from<string_view_type, rg const &&>)
explicit constexpr basic_cstring_view(::fast_io::containers::null_terminated_t, ::fast_io::freestanding::from_range_t, rg const &&r) noexcept
: string_view_type(::std::forward<rg>(r))
{
}

constexpr basic_cstring_view(::fast_io::manipulators::basic_os_c_str<char_type> osstr) noexcept
: string_view_type(osstr)
{}
constexpr basic_cstring_view(::fast_io::manipulators::basic_os_c_str_with_known_size<char_type> osstr) noexcept
: string_view_type(osstr)
{}

constexpr basic_cstring_view(basic_cstring_view const &) noexcept = default;
constexpr basic_cstring_view &operator=(basic_cstring_view const &) noexcept = default;
constexpr void swap(basic_cstring_view &other) noexcept
{
basic_cstring_view const tmp{other};
other = *this;
*this = tmp;
}
constexpr const_pointer c_str() const noexcept
{
return this->ptr;
}

using string_view_type::is_empty;
using string_view_type::empty;
using string_view_type::size;
using string_view_type::max_size;
using string_view_type::begin;
using string_view_type::cbegin;
using string_view_type::end;
using string_view_type::cend;
using string_view_type::rbegin;
using string_view_type::crbegin;
using string_view_type::rend;
using string_view_type::crend;
using string_view_type::data;
using string_view_type::index_unchecked;
using string_view_type::operator[];
using string_view_type::front;
using string_view_type::front_unchecked;
using string_view_type::back;
using string_view_type::back_unchecked;
using string_view_type::starts_with;
using string_view_type::starts_with_character;
using string_view_type::ends_with;
using string_view_type::ends_with_character;
using string_view_type::remove_prefix;
using string_view_type::remove_prefix_unchecked;
};

template <::std::integral char_type>
constexpr void swap(::fast_io::containers::basic_cstring_view<char_type> &a, basic_cstring_view<char_type> &b) noexcept
{
a.swap(b);
}
template <::std::integral char_type>
inline constexpr ::fast_io::basic_io_scatter_t<char_type> print_alias_define(::fast_io::io_alias_t, ::fast_io::containers::basic_cstring_view<char_type> str) noexcept
{
return {str.ptr, str.n};
}

template <::std::integral char_type>
constexpr bool operator==(::fast_io::containers::basic_cstring_view<char_type> a, ::fast_io::containers::basic_cstring_view<char_type> b) noexcept
{
return ::std::equal(a.ptr, a.ptr + a.n, b.ptr, b.ptr + b.n);
}

template <::std::integral char_type, ::std::size_t n>
constexpr bool operator==(::fast_io::containers::basic_cstring_view<char_type> a, char_type const (&buffer)[n]) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::equal(a.ptr, a.ptr + a.n, buffer, buffer + nm1);
}

template <::std::integral char_type, ::std::size_t n>
constexpr bool operator==(char_type const (&buffer)[n], ::fast_io::containers::basic_cstring_view<char_type> a) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::equal(buffer, buffer + nm1, a.ptr, a.ptr + a.n);
}

template <::std::integral char_type>
constexpr bool operator==(::fast_io::containers::basic_cstring_view<char_type> a, ::fast_io::containers::basic_string_view<char_type> b) noexcept
{
return ::std::equal(a.ptr, a.ptr + a.n, b.ptr, b.ptr + b.n);
}

template <::std::integral char_type>
constexpr bool operator==(::fast_io::containers::basic_string_view<char_type> a, ::fast_io::containers::basic_cstring_view<char_type> b) noexcept
{
return b == a;
}

#ifdef __cpp_lib_three_way_comparison
template <::std::integral char_type>
constexpr auto operator<=>(::fast_io::containers::basic_cstring_view<char_type> a, ::fast_io::containers::basic_cstring_view<char_type> b) noexcept
{
return ::std::lexicographical_compare_three_way(a.ptr, a.ptr + a.n, b.ptr, b.ptr + b.n, ::std::compare_three_way{});
}

template <::std::integral char_type, ::std::size_t n>
constexpr auto operator<=>(::fast_io::containers::basic_cstring_view<char_type> a, char_type const (&buffer)[n]) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::lexicographical_compare_three_way(a.ptr, a.ptr + a.n, buffer, buffer + nm1, ::std::compare_three_way{});
}

template <::std::integral char_type, ::std::size_t n>
constexpr auto operator<=>(char_type const (&buffer)[n], ::fast_io::containers::basic_cstring_view<char_type> a) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::lexicographical_compare_three_way(buffer, buffer + nm1, a.ptr, a.ptr + a.n, ::std::compare_three_way{});
}

template <::std::integral char_type>
constexpr auto operator<=>(::fast_io::containers::basic_cstring_view<char_type> a, ::fast_io::containers::basic_string_view<char_type> b) noexcept
{
return ::std::lexicographical_compare_three_way(a.ptr, a.ptr + a.n, b.ptr, b.ptr + b.n, ::std::compare_three_way{});
}

template <::std::integral char_type>
constexpr auto operator<=>(::fast_io::containers::basic_string_view<char_type> a, ::fast_io::containers::basic_cstring_view<char_type> b) noexcept
{
return ::std::lexicographical_compare_three_way(a.ptr, a.ptr + a.n, b.ptr, b.ptr + b.n, ::std::compare_three_way{});
}

#endif

} // namespace fast_io::containers
59 changes: 49 additions & 10 deletions include/fast_io_dsal/impl/string_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ class basic_string_view

inline static constexpr size_type max_size() noexcept
{
constexpr size_type n{SIZE_MAX / sizeof(value_type)};
return n;
constexpr size_type mxsz{SIZE_MAX / sizeof(value_type)};
return mxsz;
}

inline constexpr const_iterator begin() const noexcept
Expand Down Expand Up @@ -239,56 +239,95 @@ class basic_string_view
{
return !n && ch == ptr[n - 1u];
}
#if __has_cpp_attribute(__gnu__::__always_inline__)
[[__gnu__::__always_inline__]]
#elif __has_cpp_attribute(msvc::forceinline)
[[msvc::forceinline]]
#endif
inline constexpr void remove_suffix(size_type svn) noexcept
{
if (n <= svn) [[unlikely]]
{
::fast_io::fast_terminate();
}
this->n -= svn;
}

inline constexpr void remove_suffix_unchecked(size_type svn) noexcept
{
this->n -= svn;
}

#if __has_cpp_attribute(__gnu__::__always_inline__)
[[__gnu__::__always_inline__]]
#elif __has_cpp_attribute(msvc::forceinline)
[[msvc::forceinline]]
#endif
inline constexpr void remove_prefix(size_type svn) noexcept
{
if (n <= svn) [[unlikely]]
{
::fast_io::fast_terminate();
}
this->ptr += svn;
this->n -= svn;
}

inline constexpr void remove_prefix_unchecked(size_type svn) noexcept
{
this->ptr += svn;
this->n -= svn;
}
};

template <::std::integral char_type>
constexpr void swap(basic_string_view<char_type> &a, basic_string_view<char_type> &b) noexcept
constexpr void swap(::fast_io::containers::basic_string_view<char_type> &a, ::fast_io::containers::basic_string_view<char_type> &b) noexcept
{
a.swap(b);
}

template <::std::integral char_type>
inline constexpr ::fast_io::basic_io_scatter_t<char_type> print_alias_define(io_alias_t, basic_string_view<char_type> str) noexcept
inline constexpr ::fast_io::basic_io_scatter_t<char_type> print_alias_define(::fast_io::io_alias_t, ::fast_io::containers::basic_string_view<char_type> str) noexcept
{
return {str.ptr, str.n};
}

template <::std::integral char_type>
constexpr bool operator==(basic_string_view<char_type> a, basic_string_view<char_type> b) noexcept
constexpr bool operator==(::fast_io::containers::basic_string_view<char_type> a, ::fast_io::containers::basic_string_view<char_type> b) noexcept
{
return ::std::equal(a.ptr, a.ptr + a.n, b.ptr, b.ptr + b.n);
}

template <::std::integral char_type, ::std::size_t n>
constexpr bool operator==(basic_string_view<char_type> a, char_type const (&buffer)[n]) noexcept
constexpr bool operator==(::fast_io::containers::basic_string_view<char_type> a, char_type const (&buffer)[n]) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::equal(a.ptr, a.ptr + a.n, buffer, buffer + nm1);
}

template <::std::integral char_type, ::std::size_t n>
constexpr bool operator==(char_type const (&buffer)[n], basic_string_view<char_type> a) noexcept
constexpr bool operator==(char_type const (&buffer)[n], ::fast_io::containers::basic_string_view<char_type> a) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::equal(buffer, buffer + nm1, a.ptr, a.ptr + a.n);
}

#ifdef __cpp_lib_three_way_comparison
template <::std::integral char_type>
constexpr auto operator<=>(basic_string_view<char_type> a, basic_string_view<char_type> b) noexcept
constexpr auto operator<=>(::fast_io::containers::basic_string_view<char_type> a, ::fast_io::containers::basic_string_view<char_type> b) noexcept
{
return ::std::lexicographical_compare_three_way(a.ptr, a.ptr + a.n, b.ptr, b.ptr + b.n, ::std::compare_three_way{});
}

template <::std::integral char_type, ::std::size_t n>
constexpr auto operator<=>(basic_string_view<char_type> a, char_type const (&buffer)[n]) noexcept
constexpr auto operator<=>(::fast_io::containers::basic_string_view<char_type> a, char_type const (&buffer)[n]) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::lexicographical_compare_three_way(a.ptr, a.ptr + a.n, buffer, buffer + nm1, ::std::compare_three_way{});
}

template <::std::integral char_type, ::std::size_t n>
constexpr auto operator<=>(char_type const (&buffer)[n], basic_string_view<char_type> a) noexcept
constexpr auto operator<=>(char_type const (&buffer)[n], ::fast_io::containers::basic_string_view<char_type> a) noexcept
{
constexpr ::std::size_t nm1{n - 1u};
return ::std::lexicographical_compare_three_way(buffer, buffer + nm1, a.ptr, a.ptr + a.n, ::std::compare_three_way{});
Expand Down
2 changes: 2 additions & 0 deletions tests/0026.container/0010.cstring_view/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_executable(cstring_view cstring_view.cc)
add_test(cstring_view cstring_view)
14 changes: 14 additions & 0 deletions tests/0026.container/0010.cstring_view/cstring_view.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <fast_io_dsal/cstring_view.h>
#include <fast_io.h>

int main()
{
::fast_io::cstring_view stvw("hello \0world\n");
::fast_io::io::println(stvw,
stvw == "hello world\n", "\n",
"hello world\n" == stvw, "\n",
stvw <=> "hello world\n", "\n",
"hello world\n" <=> stvw, "\n",
stvw.starts_with("hello"), "\n",
stvw.ends_with("\0world\n"));
}
3 changes: 2 additions & 1 deletion tests/0026.container/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ add_subdirectory(0005.stack)
add_subdirectory(0006.queue)
add_subdirectory(0007.array)
add_subdirectory(0008.priority_queue)
add_subdirectory(0009.string_view)
add_subdirectory(0009.string_view)
add_subdirectory(0010.cstring_view)

0 comments on commit 90d5f1f

Please sign in to comment.