From c05d84a22e753d1831592c274290c7ecaf517857 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 11 Apr 2024 12:16:09 -0400 Subject: [PATCH 1/2] add cstring_view and string_view --- include/fast_io_dsal/impl/cstring_view.h | 187 ++++++++++++++++++ include/fast_io_dsal/impl/string_view.h | 59 +++++- .../0010.cstring_view/CMakeLists.txt | 2 + .../0010.cstring_view/cstring_view.cc | 14 ++ tests/0026.container/CMakeLists.txt | 3 +- 5 files changed, 254 insertions(+), 11 deletions(-) create mode 100644 include/fast_io_dsal/impl/cstring_view.h create mode 100644 tests/0026.container/0010.cstring_view/CMakeLists.txt create mode 100644 tests/0026.container/0010.cstring_view/cstring_view.cc diff --git a/include/fast_io_dsal/impl/cstring_view.h b/include/fast_io_dsal/impl/cstring_view.h new file mode 100644 index 000000000..77068c7bd --- /dev/null +++ b/include/fast_io_dsal/impl/cstring_view.h @@ -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 +{ +public: + using string_view_type = ::fast_io::containers::basic_string_view; + 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) + 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(r)) + { + } + + constexpr basic_cstring_view(::fast_io::manipulators::basic_os_c_str osstr) noexcept + : string_view_type(osstr) + {} + constexpr basic_cstring_view(::fast_io::manipulators::basic_os_c_str_with_known_size 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 &a, basic_cstring_view &b) noexcept +{ + a.swap(b); +} +template <::std::integral char_type> +inline constexpr ::fast_io::basic_io_scatter_t print_alias_define(::fast_io::io_alias_t, ::fast_io::containers::basic_cstring_view str) noexcept +{ + return {str.ptr, str.n}; +} + +template <::std::integral char_type> +constexpr bool operator==(::fast_io::containers::basic_cstring_view a, ::fast_io::containers::basic_cstring_view 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 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 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 a, ::fast_io::containers::basic_string_view 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 a, ::fast_io::containers::basic_cstring_view 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 a, ::fast_io::containers::basic_cstring_view 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 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 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 a, ::fast_io::containers::basic_string_view 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 a, ::fast_io::containers::basic_cstring_view 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 diff --git a/include/fast_io_dsal/impl/string_view.h b/include/fast_io_dsal/impl/string_view.h index bf69d4fdd..45fcbca31 100644 --- a/include/fast_io_dsal/impl/string_view.h +++ b/include/fast_io_dsal/impl/string_view.h @@ -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 @@ -239,35 +239,74 @@ 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 &a, basic_string_view &b) noexcept +constexpr void swap(::fast_io::containers::basic_string_view &a, ::fast_io::containers::basic_string_view &b) noexcept { a.swap(b); } template <::std::integral char_type> -inline constexpr ::fast_io::basic_io_scatter_t print_alias_define(io_alias_t, basic_string_view str) noexcept +inline constexpr ::fast_io::basic_io_scatter_t print_alias_define(::fast_io::io_alias_t, ::fast_io::containers::basic_string_view str) noexcept { return {str.ptr, str.n}; } template <::std::integral char_type> -constexpr bool operator==(basic_string_view a, basic_string_view b) noexcept +constexpr bool operator==(::fast_io::containers::basic_string_view a, ::fast_io::containers::basic_string_view 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 a, char_type const (&buffer)[n]) noexcept +constexpr bool operator==(::fast_io::containers::basic_string_view 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 a) noexcept +constexpr bool operator==(char_type const (&buffer)[n], ::fast_io::containers::basic_string_view a) noexcept { constexpr ::std::size_t nm1{n - 1u}; return ::std::equal(buffer, buffer + nm1, a.ptr, a.ptr + a.n); @@ -275,20 +314,20 @@ constexpr bool operator==(char_type const (&buffer)[n], basic_string_view -constexpr auto operator<=>(basic_string_view a, basic_string_view b) noexcept +constexpr auto operator<=>(::fast_io::containers::basic_string_view a, ::fast_io::containers::basic_string_view 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 a, char_type const (&buffer)[n]) noexcept +constexpr auto operator<=>(::fast_io::containers::basic_string_view 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 a) noexcept +constexpr auto operator<=>(char_type const (&buffer)[n], ::fast_io::containers::basic_string_view 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{}); diff --git a/tests/0026.container/0010.cstring_view/CMakeLists.txt b/tests/0026.container/0010.cstring_view/CMakeLists.txt new file mode 100644 index 000000000..1c332ffd8 --- /dev/null +++ b/tests/0026.container/0010.cstring_view/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(cstring_view cstring_view.cc) +add_test(cstring_view cstring_view) diff --git a/tests/0026.container/0010.cstring_view/cstring_view.cc b/tests/0026.container/0010.cstring_view/cstring_view.cc new file mode 100644 index 000000000..0735a7442 --- /dev/null +++ b/tests/0026.container/0010.cstring_view/cstring_view.cc @@ -0,0 +1,14 @@ +#include +#include + +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")); +} diff --git a/tests/0026.container/CMakeLists.txt b/tests/0026.container/CMakeLists.txt index e314710af..e831994b0 100644 --- a/tests/0026.container/CMakeLists.txt +++ b/tests/0026.container/CMakeLists.txt @@ -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) \ No newline at end of file +add_subdirectory(0009.string_view) +add_subdirectory(0010.cstring_view) \ No newline at end of file From 72392d0ae0c74ed2990e0c0ed48045949073e3da Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 11 Apr 2024 12:20:18 -0400 Subject: [PATCH 2/2] cstring_view.h missing --- include/fast_io_dsal/cstring_view.h | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 include/fast_io_dsal/cstring_view.h diff --git a/include/fast_io_dsal/cstring_view.h b/include/fast_io_dsal/cstring_view.h new file mode 100644 index 000000000..29f0a5aaf --- /dev/null +++ b/include/fast_io_dsal/cstring_view.h @@ -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 +#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; +using wcstring_view = ::fast_io::containers::basic_cstring_view; +using u8cstring_view = ::fast_io::containers::basic_cstring_view; +using u16cstring_view = ::fast_io::containers::basic_cstring_view; +using u32cstring_view = ::fast_io::containers::basic_cstring_view; + +namespace tlc +{ +using cstring_view = ::fast_io::containers::basic_cstring_view; +using wcstring_view = ::fast_io::containers::basic_cstring_view; +using u8cstring_view = ::fast_io::containers::basic_cstring_view; +using u16cstring_view = ::fast_io::containers::basic_cstring_view; +using u32cstring_view = ::fast_io::containers::basic_cstring_view; +} // namespace tlc + +} // namespace fast_io + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif