diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 61805726a4ff0..5f8151d241b49 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -394,7 +394,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_reference_from_temporary`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_spanstream`` *unimplemented* + ``__cpp_lib_spanstream`` ``202106L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_stacktrace`` *unimplemented* ---------------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index 15bf46d44b07f..cdf54b14e6b9d 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -39,6 +39,7 @@ Implemented Papers ------------------ - P2321R2: ``zip`` (`Github `__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release) +- P0448R4: A ``strstream`` replacement using ``span`` as buffer (`Github `__) Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index e4fa07d82289d..ab58bd725d9e9 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -12,7 +12,7 @@ "`P2259R1 `__","Repairing input range adaptors and counted_iterator","2021-02 (Virtual)","","","" "","","","","","" "`P0401R6 `__","Providing size feedback in the Allocator interface","2021-06 (Virtual)","|Complete|","15","" -"`P0448R4 `__","A strstream replacement using span as buffer","2021-06 (Virtual)","","","" +"`P0448R4 `__","A ``strstream`` replacement using ``span`` as buffer","2021-06 (Virtual)","|Complete|","22" "`P1132R8 `__","out_ptr - a scalable output pointer abstraction","2021-06 (Virtual)","|Complete|","19","" "`P1328R1 `__","Making std::type_info::operator== constexpr","2021-06 (Virtual)","|Complete|","17","" "`P1425R4 `__","Iterators pair constructors for stack and queue","2021-06 (Virtual)","|Complete|","14","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index cd6583cb62c24..21ef9575b8803 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -455,6 +455,7 @@ set(files __fwd/queue.h __fwd/set.h __fwd/span.h + __fwd/spanstream.h __fwd/sstream.h __fwd/stack.h __fwd/streambuf.h @@ -1056,6 +1057,7 @@ set(files shared_mutex source_location span + spanstream sstream stack stdatomic.h diff --git a/libcxx/include/__fwd/spanstream.h b/libcxx/include/__fwd/spanstream.h new file mode 100644 index 0000000000000..655a5af22fc27 --- /dev/null +++ b/libcxx/include/__fwd/spanstream.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_SPANSTREAM_H +#define _LIBCPP___FWD_SPANSTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template > +class basic_spanbuf; +template > +class basic_ispanstream; +template > +class basic_ospanstream; +template > +class basic_spanstream; + +using spanbuf = basic_spanbuf; +using ispanstream = basic_ispanstream; +using ospanstream = basic_ospanstream; +using spanstream = basic_spanstream; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +using wspanbuf = basic_spanbuf; +using wispanstream = basic_ispanstream; +using wospanstream = basic_ospanstream; +using wspanstream = basic_spanstream; +# endif + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_SPANSTREAM_H diff --git a/libcxx/include/iosfwd b/libcxx/include/iosfwd index 7f7c9417d3e70..99c0815726704 100644 --- a/libcxx/include/iosfwd +++ b/libcxx/include/iosfwd @@ -41,6 +41,15 @@ template , class Allocator = allo template , class Allocator = allocator > class basic_stringstream; + template> + class basic_spanbuf; // Since C++23 + template> + class basic_ispanstream; // Since C++23 + template> + class basic_ospanstream; // Since C++23 + template> + class basic_spanstream; // Since C++23 + template > class basic_filebuf; template > class basic_ifstream; template > class basic_ofstream; @@ -62,6 +71,11 @@ typedef basic_istringstream istringstream; typedef basic_ostringstream ostringstream; typedef basic_stringstream stringstream; +using spanbuf = basic_spanbuf; // Since C++23 +using ispanstream = basic_ispanstream; // Since C++23 +using ospanstream = basic_ospanstream; // Since C++23 +using spanstream = basic_spanstream; // Since C++23 + typedef basic_filebuf filebuf; typedef basic_ifstream ifstream; typedef basic_ofstream ofstream; @@ -77,6 +91,11 @@ typedef basic_istringstream wistringstream; typedef basic_ostringstream wostringstream; typedef basic_stringstream wstringstream; +using wspanbuf = basic_spanbuf; // Since C++23 +using wispanstream = basic_ispanstream; // Since C++23 +using wospanstream = basic_ospanstream; // Since C++23 +using wspanstream = basic_spanstream; // Since C++23 + typedef basic_filebuf wfilebuf; typedef basic_ifstream wifstream; typedef basic_ofstream wofstream; @@ -114,6 +133,7 @@ using wosyncstream = basic_osyncstream; // C++20 # include <__fwd/istream.h> # include <__fwd/memory.h> # include <__fwd/ostream.h> +# include <__fwd/spanstream.h> # include <__fwd/sstream.h> # include <__fwd/streambuf.h> # include <__fwd/string.h> diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index ac497208bdce4..880593b1e185d 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1997,6 +1997,13 @@ module std [system] { export std.iterator.reverse_iterator } + module spanstream { + module fwd { header "__fwd/spanstream.h" } + + header "spanstream" + export * + } + module sstream { module fwd { header "__fwd/sstream.h" } diff --git a/libcxx/include/spanstream b/libcxx/include/spanstream new file mode 100644 index 0000000000000..c61db77d66f45 --- /dev/null +++ b/libcxx/include/spanstream @@ -0,0 +1,470 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_SPANSTREAM +#define _LIBCPP_SPANSTREAM + +// clang-format off + +/* + Span-based streams [span.streams] + + template> + class basic_spanbuf; + + template + void swap(basic_spanbuf& x, basic_spanbuf& y); + + using spanbuf = basic_spanbuf; + using wspanbuf = basic_spanbuf; + + template> + class basic_ispanstream; + + template + void swap(basic_ispanstream& x, basic_ispanstream& y); + + using ispanstream = basic_ispanstream; + using wispanstream = basic_ispanstream; + + template> + class basic_ospanstream; + + template + void swap(basic_ospanstream& x, basic_ospanstream& y); + + using ospanstream = basic_ospanstream; + using wospanstream = basic_ospanstream; + + template> + class basic_spanstream; + + template + void swap(basic_spanstream& x, basic_spanstream& y); + + using spanstream = basic_spanstream; + using wspanstream = basic_spanstream; +*/ + +// clang-format on + +#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) +# include <__cxx03/__config> +#else + +# include <__config> + +# if _LIBCPP_HAS_LOCALIZATION + +# include <__concepts/convertible_to.h> +# include <__fwd/spanstream.h> +# include <__memory/addressof.h> +# include <__ranges/concepts.h> +# include <__utility/cmp.h> +# include <__utility/forward.h> +# include <__utility/move.h> +# include <__utility/swap.h> +# include +# include +# include +# include +# include + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 23 + +// Class template basic_spanbuf [spanbuf] + +template +class basic_spanbuf : public basic_streambuf<_CharT, _Traits> { +public: + using char_type = _CharT; + using int_type = typename _Traits::int_type; + using pos_type = typename _Traits::pos_type; + using off_type = typename _Traits::off_type; + using traits_type = _Traits; + + // [spanbuf.cons], constructors + + _LIBCPP_HIDE_FROM_ABI basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_spanbuf(ios_base::openmode __which) + : basic_spanbuf(std::span<_CharT>(), __which) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_spanbuf(std::span<_CharT> __s, + ios_base::openmode __which = ios_base::in | ios_base::out) + : basic_streambuf<_CharT, _Traits>{}, __mode_(__which) { + span(__s); + } + + basic_spanbuf(const basic_spanbuf&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_spanbuf(basic_spanbuf&& __rhs) + : basic_streambuf<_CharT, _Traits>{std::move(__rhs)}, + __mode_{std::move(__rhs.__mode_)}, + __buf_{std::move(__rhs.__buf_)} {} + + // [spanbuf.assign], assignment and swap + + basic_spanbuf& operator=(const basic_spanbuf&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_spanbuf& operator=(basic_spanbuf&& __rhs) { + basic_spanbuf __tmp{std::move(__rhs)}; + swap(__tmp); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI void swap(basic_spanbuf& __rhs) { + basic_streambuf<_CharT, _Traits>::swap(__rhs); + std::swap(__mode_, __rhs.__mode_); + std::swap(__buf_, __rhs.__buf_); + } + + // [spanbuf.members], member functions + + _LIBCPP_HIDE_FROM_ABI std::span<_CharT> span() const noexcept { + if (__mode_ & ios_base::out) { + return std::span<_CharT>{this->pbase(), this->pptr()}; + } + return __buf_; + } + + _LIBCPP_HIDE_FROM_ABI void span(std::span<_CharT> __s) noexcept { + __buf_ = __s; + + if (__mode_ & ios_base::out) { + this->setp(__s.data(), __s.data() + __s.size()); + if (__mode_ & ios_base::ate) { + this->pbump(__s.size()); + } + } + + if (__mode_ & ios_base::in) { + this->setg(__s.data(), __s.data(), __s.data() + __s.size()); + } + } + +protected: + // [spanbuf.virtuals], overridden virtual functions + + _LIBCPP_HIDE_FROM_ABI basic_streambuf<_CharT, _Traits>* setbuf(_CharT* __s, streamsize __n) override { + span(std::span<_CharT>(__s, __n)); + return this; + } + + _LIBCPP_HIDE_FROM_ABI pos_type + seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which = ios_base::in | ios_base::out) override { + const auto __error = static_cast(off_type{-1}); + + // Mode: `in` and `out` + if ((__which & ios_base::in) && (__which & ios_base::out) && (ios_base::cur == __way)) + return __error; + + // Mode: none + if (!((__which & ios_base::in) || (__which & ios_base::out)) && (ios_base::cur == __way)) + return __error; + + // Calculate `__baseoff` + + std::size_t __baseoff; + + switch (__way) { + case ios_base::beg: + __baseoff = 0Z; + break; + + case ios_base::cur: + if (__which & ios_base::out) + __baseoff = this->pptr() - this->pbase(); + else + __baseoff = this->gptr() - this->eback(); + break; + + case ios_base::end: + if ((__mode_ & ios_base::out) && !(__mode_ & ios_base::in)) + __baseoff = this->pptr() - this->pbase(); + else + __baseoff = __buf_.size(); + break; + + default: + return __error; + }; + + // Calculate `__newoff` + + off_type __newoff; + + if (__builtin_add_overflow(__baseoff, __off, std::addressof(__newoff)) || (__newoff < off_type{0}) || + std::cmp_greater(__newoff, __buf_.size())) + return __error; + + // Set pointers + + if (__which & ios_base::in) { + if ((this->gptr() == nullptr) && (__newoff != off_type{0})) + return __error; + this->setg(this->eback(), this->eback() + __newoff, this->egptr()); + } + + if (__which & ios_base::out) { + if ((this->pptr() == nullptr) && (__newoff != off_type{0})) + return __error; + this->setp(this->pbase(), this->epptr()); + this->pbump(__newoff); + } + + return static_cast(__newoff); + } + + _LIBCPP_HIDE_FROM_ABI pos_type seekpos(pos_type __sp, + ios_base::openmode __which = ios_base::in | ios_base::out) override { + return seekoff(static_cast(__sp), ios_base::beg, __which); + } + +private: + ios_base::openmode __mode_; + std::span<_CharT> __buf_; +}; + +template +_LIBCPP_HIDE_FROM_ABI void swap(basic_spanbuf<_CharT, _Traits>& __x, basic_spanbuf<_CharT, _Traits>& __y) { + __x.swap(__y); +} + +using std::spanbuf; +# if _LIBCPP_HAS_WIDE_CHARACTERS +using std::wspanbuf; +# endif + +// Class template basic_ispanstream [ispanstream] + +template +class basic_ispanstream : public basic_istream<_CharT, _Traits> { +public: + using char_type = _CharT; + using int_type = typename _Traits::int_type; + using pos_type = typename _Traits::pos_type; + using off_type = typename _Traits::off_type; + using traits_type = _Traits; + + // [ispanstream.cons], constructors + + _LIBCPP_HIDE_FROM_ABI explicit basic_ispanstream(std::span<_CharT> __s, ios_base::openmode __which = ios_base::in) + : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), + __sb_(basic_spanbuf<_CharT, _Traits>(__s, __which | ios_base::in)) {} + + basic_ispanstream(const basic_ispanstream&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_ispanstream(basic_ispanstream&& __rhs) + : basic_istream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) { + basic_istream<_CharT, _Traits>::set_rdbuf(std::addressof(__sb_)); + } + + template + requires(!convertible_to<_ROSeq, std::span<_CharT>>) && convertible_to<_ROSeq, std::span> + _LIBCPP_HIDE_FROM_ABI explicit basic_ispanstream(_ROSeq&& __s) + : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(basic_spanbuf<_CharT, _Traits>(ios_base::in)) { + std::span __sp(std::forward<_ROSeq>(__s)); + this->span(std::span<_CharT>(const_cast<_CharT*>(__sp.data()), __sp.size())); + } + + basic_ispanstream& operator=(const basic_ispanstream&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_ispanstream& operator=(basic_ispanstream&& __rhs) { + basic_ispanstream __tmp{std::move(__rhs)}; + this->swap(__tmp); + return *this; + } + + // [ispanstream.swap], swap + + _LIBCPP_HIDE_FROM_ABI void swap(basic_ispanstream& __rhs) { + basic_istream<_CharT, _Traits>::swap(__rhs); + __sb_.swap(__rhs.__sb_); + } + + // [ispanstream.members], member functions + + _LIBCPP_HIDE_FROM_ABI basic_spanbuf<_CharT, _Traits>* rdbuf() const noexcept { + return const_cast*>(std::addressof(__sb_)); + } + + _LIBCPP_HIDE_FROM_ABI std::span span() const noexcept { return rdbuf()->span(); } + + _LIBCPP_HIDE_FROM_ABI void span(std::span<_CharT> __s) noexcept { rdbuf()->span(__s); } + + template + requires(!convertible_to<_ROSeq, std::span<_CharT>>) && convertible_to<_ROSeq, std::span> + _LIBCPP_HIDE_FROM_ABI void span(_ROSeq&& __s) noexcept { + std::span __sp(std::forward<_ROSeq>(__s)); + this->span(std::span<_CharT>(const_cast<_CharT*>(__sp.data()), __sp.size())); + } + +private: + basic_spanbuf<_CharT, _Traits> __sb_; +}; + +template +_LIBCPP_HIDE_FROM_ABI void swap(basic_ispanstream<_CharT, _Traits>& __x, basic_ispanstream<_CharT, _Traits>& __y) { + __x.swap(__y); +} + +using std::ispanstream; +# if _LIBCPP_HAS_WIDE_CHARACTERS +using std::wispanstream; +# endif + +// Class template basic_ospanstream [ospanstream] + +template +class basic_ospanstream : public basic_ostream<_CharT, _Traits> { +public: + using char_type = _CharT; + using int_type = typename _Traits::int_type; + using pos_type = typename _Traits::pos_type; + using off_type = typename _Traits::off_type; + using traits_type = _Traits; + + // [ospanstream.cons], constructors + + _LIBCPP_HIDE_FROM_ABI explicit basic_ospanstream(std::span<_CharT> __s, ios_base::openmode __which = ios_base::out) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), + __sb_(basic_spanbuf<_CharT, _Traits>(__s, __which | ios_base::out)) {} + + basic_ospanstream(const basic_ospanstream&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_ospanstream(basic_ospanstream&& __rhs) + : basic_ostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) { + basic_ostream<_CharT, _Traits>::set_rdbuf(std::addressof(__sb_)); + } + + basic_ospanstream& operator=(const basic_ospanstream&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_ospanstream& operator=(basic_ospanstream&& __rhs) { + basic_ospanstream __tmp{std::move(__rhs)}; + this->swap(__tmp); + return *this; + } + + // [ospanstream.swap], swap + + _LIBCPP_HIDE_FROM_ABI void swap(basic_ospanstream& __rhs) { + basic_ostream<_CharT, _Traits>::swap(__rhs); + __sb_.swap(__rhs.__sb_); + } + + // [ospanstream.members], member functions + + _LIBCPP_HIDE_FROM_ABI basic_spanbuf<_CharT, _Traits>* rdbuf() const noexcept { + return const_cast*>(std::addressof(__sb_)); + } + + _LIBCPP_HIDE_FROM_ABI std::span<_CharT> span() const noexcept { return rdbuf()->span(); } + + _LIBCPP_HIDE_FROM_ABI void span(std::span<_CharT> __s) noexcept { rdbuf()->span(__s); } + +private: + basic_spanbuf<_CharT, _Traits> __sb_; +}; + +template +_LIBCPP_HIDE_FROM_ABI void swap(basic_ospanstream<_CharT, _Traits>& __x, basic_ospanstream<_CharT, _Traits>& __y) { + __x.swap(__y); +} + +using std::ospanstream; +# if _LIBCPP_HAS_WIDE_CHARACTERS +using std::wospanstream; +# endif + +template +class basic_spanstream : public basic_iostream<_CharT, _Traits> { +public: + using char_type = _CharT; + using int_type = typename _Traits::int_type; + using pos_type = typename _Traits::pos_type; + using off_type = typename _Traits::off_type; + using traits_type = _Traits; + + // [spanstream.cons], constructors + + _LIBCPP_HIDE_FROM_ABI explicit basic_spanstream(std::span<_CharT> __s, + ios_base::openmode __which = ios_base::out | ios_base::in) + : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(basic_spanbuf<_CharT, _Traits>(__s, __which)) {} + + basic_spanstream(const basic_spanstream&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_spanstream(basic_spanstream&& __rhs) + : basic_iostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) { + basic_iostream<_CharT, _Traits>::set_rdbuf(std::addressof(__sb_)); + } + + basic_spanstream& operator=(const basic_spanstream&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_spanstream& operator=(basic_spanstream&& __rhs) { + basic_spanstream __tmp{std::move(__rhs)}; + this->swap(__tmp); + return *this; + } + + // [spanstream.swap], swap + + _LIBCPP_HIDE_FROM_ABI void swap(basic_spanstream& __rhs) { + basic_iostream<_CharT, _Traits>::swap(__rhs); + __sb_.swap(__rhs.__sb_); + } + + // [spanstream.members], members + + _LIBCPP_HIDE_FROM_ABI basic_spanbuf<_CharT, _Traits>* rdbuf() const noexcept { + return const_cast*>(std::addressof(__sb_)); + } + + _LIBCPP_HIDE_FROM_ABI std::span<_CharT> span() const noexcept { return rdbuf()->span(); } + + _LIBCPP_HIDE_FROM_ABI void span(std::span<_CharT> __s) noexcept { rdbuf()->span(__s); } + +private: + basic_spanbuf<_CharT, _Traits> __sb_; +}; + +template +_LIBCPP_HIDE_FROM_ABI void swap(basic_spanstream<_CharT, _Traits>& __x, basic_spanstream<_CharT, _Traits>& __y) { + __x.swap(__y); +} + +using std::spanstream; +# if _LIBCPP_HAS_WIDE_CHARACTERS +using std::wspanstream; +# endif + +# endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +# endif // _LIBCPP_HAS_LOCALIZATION + +# if _LIBCPP_STD_VER <= 20 && !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) +# include +# endif + +#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) + +#endif // _LIBCPP_SPANSTREAM diff --git a/libcxx/include/version b/libcxx/include/version index d98049bd57046..a83f7b36958c5 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -530,7 +530,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_ranges_to_container 202202L // # define __cpp_lib_ranges_zip 202110L // # define __cpp_lib_reference_from_temporary 202202L -// # define __cpp_lib_spanstream 202106L +# define __cpp_lib_spanstream 202106L // # define __cpp_lib_stacktrace 202011L # define __cpp_lib_stdatomic_h 202011L # define __cpp_lib_string_contains 202011L diff --git a/libcxx/modules/std.compat.cppm.in b/libcxx/modules/std.compat.cppm.in index dd7385bf33a42..b4222ba307c2d 100644 --- a/libcxx/modules/std.compat.cppm.in +++ b/libcxx/modules/std.compat.cppm.in @@ -66,9 +66,6 @@ module; # if __has_include() # error "please update the header information for in headers_not_available in utils/libcxx/header_information.py" # endif // __has_include() -# if __has_include() -# error "please update the header information for in headers_not_available in utils/libcxx/header_information.py" -# endif // __has_include() # if __has_include() # error "please update the header information for in headers_not_available in utils/libcxx/header_information.py" # endif // __has_include() diff --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in index 984b18321923c..c25397ab64f52 100644 --- a/libcxx/modules/std.cppm.in +++ b/libcxx/modules/std.cppm.in @@ -100,6 +100,7 @@ module; #include #include #include +#include #include #include #include @@ -150,9 +151,6 @@ module; # if __has_include() # error "please update the header information for in headers_not_available in utils/libcxx/header_information.py" # endif // __has_include() -# if __has_include() -# error "please update the header information for in headers_not_available in utils/libcxx/header_information.py" -# endif // __has_include() # if __has_include() # error "please update the header information for in headers_not_available in utils/libcxx/header_information.py" # endif // __has_include() diff --git a/libcxx/modules/std/spanstream.inc b/libcxx/modules/std/spanstream.inc index e5b096e993307..f299bf02c25da 100644 --- a/libcxx/modules/std/spanstream.inc +++ b/libcxx/modules/std/spanstream.inc @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// export namespace std { -#if 0 +#if _LIBCPP_STD_VER >= 23 using std::basic_spanbuf; using std::swap; @@ -38,5 +38,5 @@ export namespace std { # if _LIBCPP_HAS_WIDE_CHARACTERS using std::wspanstream; # endif -#endif +#endif // _LIBCPP_STD_VER >= 23 } // namespace std diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv index c0031543e47bc..10d713a53a376 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -122,15 +122,19 @@ atomic ratio atomic type_traits atomic version barrier atomic +barrier cctype barrier climits barrier cmath barrier compare barrier concepts barrier cstddef barrier cstdint +barrier cstdio barrier cstdlib barrier cstring barrier ctime +barrier cwchar +barrier cwctype barrier exception barrier initializer_list barrier iosfwd @@ -1922,6 +1926,62 @@ span utility span variant span vector span version +spanstream algorithm +spanstream array +spanstream atomic +spanstream bit +spanstream bitset +spanstream cctype +spanstream cerrno +spanstream climits +spanstream clocale +spanstream cmath +spanstream compare +spanstream concepts +spanstream cstdarg +spanstream cstddef +spanstream cstdint +spanstream cstdio +spanstream cstdlib +spanstream cstring +spanstream ctime +spanstream cwchar +spanstream cwctype +spanstream deque +spanstream exception +spanstream format +spanstream functional +spanstream initializer_list +spanstream ios +spanstream iosfwd +spanstream iostream +spanstream istream +spanstream iterator +spanstream limits +spanstream locale +spanstream memory +spanstream mutex +spanstream new +spanstream optional +spanstream ostream +spanstream print +spanstream queue +spanstream ratio +spanstream span +spanstream stack +spanstream stdexcept +spanstream streambuf +spanstream string +spanstream string_view +spanstream system_error +spanstream tuple +spanstream type_traits +spanstream typeinfo +spanstream unordered_map +spanstream utility +spanstream variant +spanstream vector +spanstream version sstream algorithm sstream array sstream atomic @@ -2032,6 +2092,7 @@ stdexcept new stdexcept type_traits stdexcept typeinfo stdexcept version +stop_token cstddef stop_token iosfwd stop_token version streambuf algorithm diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv index c0031543e47bc..10d713a53a376 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -122,15 +122,19 @@ atomic ratio atomic type_traits atomic version barrier atomic +barrier cctype barrier climits barrier cmath barrier compare barrier concepts barrier cstddef barrier cstdint +barrier cstdio barrier cstdlib barrier cstring barrier ctime +barrier cwchar +barrier cwctype barrier exception barrier initializer_list barrier iosfwd @@ -1922,6 +1926,62 @@ span utility span variant span vector span version +spanstream algorithm +spanstream array +spanstream atomic +spanstream bit +spanstream bitset +spanstream cctype +spanstream cerrno +spanstream climits +spanstream clocale +spanstream cmath +spanstream compare +spanstream concepts +spanstream cstdarg +spanstream cstddef +spanstream cstdint +spanstream cstdio +spanstream cstdlib +spanstream cstring +spanstream ctime +spanstream cwchar +spanstream cwctype +spanstream deque +spanstream exception +spanstream format +spanstream functional +spanstream initializer_list +spanstream ios +spanstream iosfwd +spanstream iostream +spanstream istream +spanstream iterator +spanstream limits +spanstream locale +spanstream memory +spanstream mutex +spanstream new +spanstream optional +spanstream ostream +spanstream print +spanstream queue +spanstream ratio +spanstream span +spanstream stack +spanstream stdexcept +spanstream streambuf +spanstream string +spanstream string_view +spanstream system_error +spanstream tuple +spanstream type_traits +spanstream typeinfo +spanstream unordered_map +spanstream utility +spanstream variant +spanstream vector +spanstream version sstream algorithm sstream array sstream atomic @@ -2032,6 +2092,7 @@ stdexcept new stdexcept type_traits stdexcept typeinfo stdexcept version +stop_token cstddef stop_token iosfwd stop_token version streambuf algorithm diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv index c2eb5b44e8d7a..d93fbe1d82980 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -125,15 +125,19 @@ atomic ratio atomic type_traits atomic version barrier atomic +barrier cctype barrier climits barrier cmath barrier compare barrier concepts barrier cstddef barrier cstdint +barrier cstdio barrier cstdlib barrier cstring barrier ctime +barrier cwchar +barrier cwctype barrier exception barrier initializer_list barrier iosfwd @@ -1960,6 +1964,63 @@ span utility span variant span vector span version +spanstream algorithm +spanstream array +spanstream atomic +spanstream bit +spanstream bitset +spanstream cctype +spanstream cerrno +spanstream climits +spanstream clocale +spanstream cmath +spanstream compare +spanstream concepts +spanstream cstdarg +spanstream cstddef +spanstream cstdint +spanstream cstdio +spanstream cstdlib +spanstream cstring +spanstream ctime +spanstream cwchar +spanstream cwctype +spanstream deque +spanstream exception +spanstream execution +spanstream format +spanstream functional +spanstream initializer_list +spanstream ios +spanstream iosfwd +spanstream iostream +spanstream istream +spanstream iterator +spanstream limits +spanstream locale +spanstream memory +spanstream mutex +spanstream new +spanstream optional +spanstream ostream +spanstream print +spanstream queue +spanstream ratio +spanstream span +spanstream stack +spanstream stdexcept +spanstream streambuf +spanstream string +spanstream string_view +spanstream system_error +spanstream tuple +spanstream type_traits +spanstream typeinfo +spanstream unordered_map +spanstream utility +spanstream variant +spanstream vector +spanstream version sstream algorithm sstream array sstream atomic @@ -2072,6 +2133,7 @@ stdexcept new stdexcept type_traits stdexcept typeinfo stdexcept version +stop_token cstddef stop_token iosfwd stop_token version streambuf algorithm diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv index 332cb62f35b5f..439650d690378 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -122,15 +122,19 @@ atomic ratio atomic type_traits atomic version barrier atomic +barrier cctype barrier climits barrier cmath barrier compare barrier concepts barrier cstddef barrier cstdint +barrier cstdio barrier cstdlib barrier cstring barrier ctime +barrier cwchar +barrier cwctype barrier exception barrier initializer_list barrier iosfwd @@ -1975,6 +1979,62 @@ span utility span variant span vector span version +spanstream algorithm +spanstream array +spanstream atomic +spanstream bit +spanstream bitset +spanstream cctype +spanstream cerrno +spanstream climits +spanstream clocale +spanstream cmath +spanstream compare +spanstream concepts +spanstream cstdarg +spanstream cstddef +spanstream cstdint +spanstream cstdio +spanstream cstdlib +spanstream cstring +spanstream ctime +spanstream cwchar +spanstream cwctype +spanstream deque +spanstream exception +spanstream format +spanstream functional +spanstream initializer_list +spanstream ios +spanstream iosfwd +spanstream iostream +spanstream istream +spanstream iterator +spanstream limits +spanstream locale +spanstream memory +spanstream mutex +spanstream new +spanstream optional +spanstream ostream +spanstream print +spanstream queue +spanstream ratio +spanstream span +spanstream stack +spanstream stdexcept +spanstream streambuf +spanstream string +spanstream string_view +spanstream system_error +spanstream tuple +spanstream type_traits +spanstream typeinfo +spanstream unordered_map +spanstream utility +spanstream variant +spanstream vector +spanstream version sstream algorithm sstream array sstream atomic @@ -2085,6 +2145,7 @@ stdexcept new stdexcept type_traits stdexcept typeinfo stdexcept version +stop_token cstddef stop_token iosfwd stop_token version streambuf algorithm diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv index 55c79acff5a8f..af671adbfd223 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -1993,6 +1993,62 @@ span utility span variant span vector span version +spanstream algorithm +spanstream array +spanstream atomic +spanstream bit +spanstream bitset +spanstream cctype +spanstream cerrno +spanstream climits +spanstream clocale +spanstream cmath +spanstream compare +spanstream concepts +spanstream cstdarg +spanstream cstddef +spanstream cstdint +spanstream cstdio +spanstream cstdlib +spanstream cstring +spanstream ctime +spanstream cwchar +spanstream cwctype +spanstream deque +spanstream exception +spanstream format +spanstream functional +spanstream initializer_list +spanstream ios +spanstream iosfwd +spanstream iostream +spanstream istream +spanstream iterator +spanstream limits +spanstream locale +spanstream memory +spanstream mutex +spanstream new +spanstream optional +spanstream ostream +spanstream print +spanstream queue +spanstream ratio +spanstream span +spanstream stack +spanstream stdexcept +spanstream streambuf +spanstream string +spanstream string_view +spanstream system_error +spanstream tuple +spanstream type_traits +spanstream typeinfo +spanstream unordered_map +spanstream utility +spanstream variant +spanstream vector +spanstream version sstream algorithm sstream array sstream atomic diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index cb23c7a98de1b..e0b2f5b145207 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -886,6 +886,42 @@ span initializer_list span limits span stdexcept span version +spanstream array +spanstream bitset +spanstream cctype +spanstream cerrno +spanstream climits +spanstream clocale +spanstream cmath +spanstream compare +spanstream cstddef +spanstream cstdint +spanstream cstdio +spanstream cstdlib +spanstream cstring +spanstream ctime +spanstream cwchar +spanstream cwctype +spanstream format +spanstream initializer_list +spanstream ios +spanstream iosfwd +spanstream iostream +spanstream istream +spanstream limits +spanstream locale +spanstream optional +spanstream ostream +spanstream print +spanstream ratio +spanstream span +spanstream stdexcept +spanstream streambuf +spanstream string +spanstream string_view +spanstream tuple +spanstream typeinfo +spanstream version sstream bitset sstream cctype sstream cerrno diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index 5f906338f4b7c..c5a010511f44e 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -872,6 +872,41 @@ span initializer_list span limits span stdexcept span version +spanstream array +spanstream bitset +spanstream cctype +spanstream cerrno +spanstream climits +spanstream clocale +spanstream cmath +spanstream compare +spanstream cstddef +spanstream cstdint +spanstream cstdio +spanstream cstdlib +spanstream cstring +spanstream ctime +spanstream cwchar +spanstream cwctype +spanstream format +spanstream initializer_list +spanstream ios +spanstream iosfwd +spanstream iostream +spanstream istream +spanstream limits +spanstream optional +spanstream ostream +spanstream print +spanstream ratio +spanstream span +spanstream stdexcept +spanstream streambuf +spanstream string +spanstream string_view +spanstream tuple +spanstream typeinfo +spanstream version sstream bitset sstream cctype sstream cerrno diff --git a/libcxx/test/std/input.output/iostream.forward/iosfwd.pass.cpp b/libcxx/test/std/input.output/iostream.forward/iosfwd.pass.cpp index 85fc5de128ceb..930e0b5512aae 100644 --- a/libcxx/test/std/input.output/iostream.forward/iosfwd.pass.cpp +++ b/libcxx/test/std/input.output/iostream.forward/iosfwd.pass.cpp @@ -74,6 +74,29 @@ int main(int, char**) test* >(); #endif +#if TEST_STD_VER >= 23 + test*>(); + test*>(); +# ifndef TEST_HAS_NO_WIDE_CHARACTERS + test*>(); +# endif + test*>(); + test*>(); +# ifndef TEST_HAS_NO_WIDE_CHARACTERS + test*>(); +# endif + test*>(); + test*>(); +# ifndef TEST_HAS_NO_WIDE_CHARACTERS + test*>(); +# endif + test*>(); + test*>(); +# ifndef TEST_HAS_NO_WIDE_CHARACTERS + test*>(); +# endif +#endif // TEST_STD_VER >= 23 + test* >(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS test* >(); @@ -119,6 +142,13 @@ int main(int, char**) test(); test(); +#if TEST_STD_VER >= 23 + test(); + test(); + test(); + test(); +#endif // TEST_STD_VER >= 23 + test(); test(); test(); @@ -135,6 +165,13 @@ int main(int, char**) test(); test(); +# if TEST_STD_VER >= 23 + test(); + test(); + test(); + test(); +# endif // TEST_STD_VER >= 23 + test(); test(); test(); diff --git a/libcxx/test/std/input.output/span.streams/helper_functions.h b/libcxx/test/std/input.output/span.streams/helper_functions.h new file mode 100644 index 0000000000000..5a3a8a10c7fd5 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/helper_functions.h @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_INPUTOUTPUT_SPANSTREAMS_FUNCTIONS_H +#define TEST_STD_INPUTOUTPUT_SPANSTREAMS_FUNCTIONS_H + +#include + +template > +void initialize_array_from_string_view(CharT* arr, std::basic_string_view sv) { + for (std::size_t i = 0; i != sv.size(); ++i) { + arr[i] = sv[i]; + } +} + +#endif // TEST_STD_INPUTOUTPUT_SPANSTREAMS_FUNCTIONS_H diff --git a/libcxx/test/std/input.output/span.streams/helper_macros.h b/libcxx/test/std/input.output/span.streams/helper_macros.h new file mode 100644 index 0000000000000..fdbfbe68220bf --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/helper_macros.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_INPUTOUTPUT_SPANSTREAMS_MACROS_H +#define TEST_STD_INPUTOUTPUT_SPANSTREAMS_MACROS_H + +#include + +#include "make_string.h" + +// Helper macros for creating strings and string views + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +# define CH(C) (std::is_same_v ? L##C : C) +#else +# define CH(C) C +#endif // TEST_HAS_NO_WIDE_CHARACTERS +#define CS(S) MAKE_CSTRING(CharT, S) +#define ST(S, a) std::basic_string(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S), a) +#define SV(S) std::basic_string_view(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S)) + +#endif // TEST_STD_INPUTOUTPUT_SPANSTREAMS_MACROS_H diff --git a/libcxx/test/std/input.output/span.streams/helper_types.h b/libcxx/test/std/input.output/span.streams/helper_types.h new file mode 100644 index 0000000000000..a4eb47cc09fd3 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/helper_types.h @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_INPUTOUTPUT_SPANSTREAMS_TYPES_H +#define TEST_STD_INPUTOUTPUT_SPANSTREAMS_TYPES_H + +#include +#include +#include +#include + +#include "test_macros.h" + +// ROS types + +template +class ReadOnlySpan { +public: + explicit ReadOnlySpan(CharT (&arr)[N]) : arr_{arr}, size_{N} {} + + operator std::span() = delete; + + operator std::span() { return std::span{arr_}; } + + const CharT* begin() { return arr_; } + const CharT* end() { return arr_ + N; } + + std::size_t size() const { return size_; } + +private: + CharT* arr_; + std::size_t size_; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = true; + +// Constraints: Constructors [ispanstream.cons] + +static_assert(std::ranges::borrowed_range>); + +static_assert(!std::constructible_from, ReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const ReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(std::constructible_from, ReadOnlySpan>); +static_assert(std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const ReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + +static_assert(std::ranges::borrowed_range>); + +static_assert(!std::constructible_from, ReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const ReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(std::constructible_from, ReadOnlySpan>); +static_assert(std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const ReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); +#endif + +template +class NonReadOnlySpan { +public: + explicit NonReadOnlySpan(CharT (&arr)[N]) : arr_{arr} {} + + operator std::span() { return std::span{arr_}; } + + operator std::span() = delete; + + CharT* begin() { return arr_; } + CharT* end() { return arr_ + N; } + +private: + CharT* arr_; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = true; + +// Constraints: Constructors [ispanstream.cons] + +static_assert(std::ranges::borrowed_range>); + +static_assert(std::constructible_from, NonReadOnlySpan>); +static_assert(std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const NonReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(std::constructible_from, NonReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const NonReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::ranges::borrowed_range>); + +static_assert(std::constructible_from, NonReadOnlySpan>); +static_assert(std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const NonReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(std::constructible_from, NonReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); + +static_assert(!std::constructible_from, const NonReadOnlySpan>); +static_assert(!std::convertible_to, std::span>); +#endif + +// Mode types + +struct NonMode {}; + +// Spanbuffer wrapper + +template +class spanbuf_wrapper : public std::basic_spanbuf { +public: + using std::basic_spanbuf::eback; + using std::basic_spanbuf::egptr; + using std::basic_spanbuf::epptr; + using std::basic_spanbuf::gptr; + using std::basic_spanbuf::pbase; + using std::basic_spanbuf::pptr; +}; + +#endif // TEST_STD_INPUTOUTPUT_SPANSTREAMS_TYPES_H diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/inherited.stream.ops.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/inherited.stream.ops.pass.cpp new file mode 100644 index 0000000000000..1158d3e4430b9 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/inherited.stream.ops.pass.cpp @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// Test stream operations inherited from `basic_istream` + +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "test_macros.h" + +#include "../helper_functions.h" +#include "../helper_macros.h" +#include "../helper_types.h" + +template +void test_ispanstream(std::basic_ispanstream& spSt, std::size_t size) { + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + assert(spSt.span().size() == size); + + // Read from stream + std::basic_string str1; + spSt >> str1; + int i1; + spSt >> i1; + std::basic_string str2; + spSt >> str2; + int i2; + spSt >> i2; + std::basic_string str3; + spSt >> str3; + int i3; + spSt >> i3; + + assert(str1 == CS("zmt")); + assert(i1 == 94); + assert(str2 == CS("hkt")); + assert(i2 == 82); + assert(str3 == CS("pir")); + assert(i3 == 43); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + + spSt.clear(); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); +} + +template > +void test() { + using SpStream = std::basic_ispanstream; + + constexpr std::basic_string_view sv{SV("zmt 94 hkt 82 pir 43vr")}; + assert(sv.size() < 30UZ); + + { + // Create a std::span test value + CharT arr[30UZ]{}; + initialize_array_from_string_view(arr, sv); + + std::span sp{arr}; + + // std::span` + Mode: default (`in`) + { + SpStream spSt(sp); + test_ispanstream(spSt, 30UZ); + } + // std::span` + Mode: explicit `in` + { + SpStream spSt(sp, std::ios_base::in); + test_ispanstream(spSt, 30UZ); + } + } + + { + // Create a "Read Only Sequence" test value + CharT arr[30UZ]{}; + initialize_array_from_string_view(arr, sv); + + ReadOnlySpan ros{arr}; + assert(ros.size() == 30UZ); + + { + SpStream spSt(ros); + test_ispanstream(spSt, 30UZ); + } + { + SpStream spSt(std::move(ros)); + test_ispanstream(spSt, 30UZ); + } + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + // test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/assign.move.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/assign.move.pass.cpp new file mode 100644 index 0000000000000..6276a31ca3f23 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/assign.move.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { + +// // [spanbuf.cons], constructors +// +// basic_ispanstream& operator=(basic_ispanstream&& rhs); + +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(!sp.empty()); + assert(sp.size() == 4); + + // Mode: default (`in`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } + // Mode: explicit `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.move.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.move.pass.cpp new file mode 100644 index 0000000000000..a79d19bff5024 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.move.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { + +// // [spanbuf.cons], constructors +// +// basic_ispanstream(basic_ispanstream&& rhs); + +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(!sp.empty()); + assert(sp.size() == 4); + + // Mode: default (`in`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::move(rhsSpSt)); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } + // Mode: explicit `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::move(rhsSpSt)); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.ros.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.ros.pass.cpp new file mode 100644 index 0000000000000..c7152471ea70a --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.ros.pass.cpp @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { + +// // [spanbuf.cons], constructors +// +// template explicit basic_ispanstream(ROS&& s); + +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_convertible.h" +#include "test_macros.h" + +#include "../../helper_types.h" + +template > +void test_sfinae() { + using SpStream = std::basic_ispanstream; + + // Non-const convertible + static_assert(std::constructible_from>); + static_assert(!test_convertible>()); + + // Const convertible + static_assert(!std::constructible_from>); + static_assert(!test_convertible>()); + + // Non-const non-convertible + static_assert(std::constructible_from>); + static_assert(!test_convertible>()); + + // Const non-convertible + static_assert(!std::constructible_from>); + static_assert(!test_convertible>()); +} + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + ReadOnlySpan ros{arr}; + assert(ros.size() == 4); + + { + SpStream spSt(ros); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + { + SpStream spSt(std::move(ros)); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_sfinae(); +#endif + + test_sfinae(); + test_sfinae>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_sfinae(); + test_sfinae>(); +#endif + +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.span.mode.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.span.mode.pass.cpp new file mode 100644 index 0000000000000..7a813b8e8eac7 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.cons/ctor.span.mode.pass.cpp @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { + +// // [ispanstream.cons], constructors +// +// explicit basic_ispanstream(std::span s, +// ios_base::openmode which = ios_base::in); + +#include +#include +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_convertible.h" +#include "test_macros.h" + +#include "../../helper_types.h" + +template > +void test_sfinae() { + using SpStream = std::basic_ispanstream; + + // Mode + static_assert(std::constructible_from, std::ios_base::openmode>); + static_assert(!test_convertible, std::ios_base::openmode>()); + + // Non-mode + static_assert(!std::constructible_from, const NonMode>); + static_assert(!test_convertible, const NonMode>()); +} + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in`) + { + SpStream spSt{sp}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + { + SpStream spSt{std::as_const(sp)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +#ifndef TEST_HAS_NO_NASTY_STRING + // Test implicit construction from a string + if constexpr (!std::same_as) { + std::basic_string str; + { + SpStream spSt{str}; + assert(spSt.span().data() == str.data()); + assert(spSt.span().size() == 0); + } + { + SpStream spSt{std::as_const(str)}; + assert(spSt.span().data() == str.data()); + assert(spSt.span().size() == 0); + } + } +#endif + // Mode: explicit `in` + { + SpStream spSt{sp, std::ios_base::in}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + { + SpStream spSt{std::as_const(sp), std::ios_base::in}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_sfinae(); +#endif + + test_sfinae(); + test_sfinae>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_sfinae(); + test_sfinae>(); +#endif + +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.general/lit.local.cfg b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.general/lit.local.cfg new file mode 100644 index 0000000000000..2cb10010c4507 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.general/lit.local.cfg @@ -0,0 +1,3 @@ +# All non-trivial uses of iostreams require localization support +if "no-localization" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.general/nothing_to_do.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.general/nothing_to_do.pass.cpp new file mode 100644 index 0000000000000..10fc760544714 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.general/nothing_to_do.pass.cpp @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// [ispanstream.general] + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/rdbuf.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/rdbuf.pass.cpp new file mode 100644 index 0000000000000..c43b1370fd9bf --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/rdbuf.pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_istream { + +// // [ospanstream.members], members +// basic_spanbuf* rdbuf() const noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +#include "../../helper_types.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in`) + { + SpStream spSt{sp}; + auto* spBuf = static_cast*>(spSt.rdbuf()); + + assert(spBuf->span().size() == 4); + assert(spBuf->span().data() == arr); + assert(spBuf->eback() == arr); + assert(spBuf->gptr() == arr); + assert(spBuf->egptr() == arr + 4); + assert(spBuf->pbase() == nullptr); + assert(spBuf->pptr() == nullptr); + assert(spBuf->epptr() == nullptr); + } + // Mode: explicit `in` + { + SpStream spSt{sp, std::ios_base::in}; + assert(spSt.rdbuf()->span().data() == arr); + assert(spSt.rdbuf()->span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/span.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/span.pass.cpp new file mode 100644 index 0000000000000..95b2c9d48eb38 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/span.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { + +// // [ispanstream.members], members + +// std::span span() const noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` ) + { + SpStream spSt{sp}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode: `in` + { + SpStream spSt{sp, std::ios_base::in}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/span.span.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/span.span.pass.cpp new file mode 100644 index 0000000000000..b6341d7843106 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.members/span.span.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { + +// // [ispanstream.members], members + +// void span(std::span s) noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + // Mode: default (`in` ) + { + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode: `in` + { + SpStream spSt{std::span{}, std::ios_base::in}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.swap/swap.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.swap/swap.pass.cpp new file mode 100644 index 0000000000000..2772e6922df05 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.swap/swap.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { + +// // [ispanstream.swap], swap +// void swap(basic_ispanstream& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.swap/swap_nonmember.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.swap/swap_nonmember.pass.cpp new file mode 100644 index 0000000000000..e2a8837d56399 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/ispanstream.swap/swap_nonmember.pass.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template +// void swap(basic_ispanstream& x, basic_ispanstream& y); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ispanstream/types.compile.pass.cpp b/libcxx/test/std/input.output/span.streams/ispanstream/types.compile.pass.cpp new file mode 100644 index 0000000000000..b815f4abc34db --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ispanstream/types.compile.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ispanstream +// : public basic_istream { +// public: +// using char_type = charT; +// using int_type = typename traits::int_type; +// using pos_type = typename traits::pos_type; +// using off_type = typename traits::off_type; +// using traits_type = traits; + +// using ispanstream = basic_ispanstream; +// using wispanstream = basic_ispanstream; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ispanstream; + + // Constructors + + static_assert(!std::is_default_constructible_v); + + // Types + + static_assert(std::is_base_of_v, SpStream>); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + // Copy properties + + static_assert(!std::is_copy_constructible_v); + static_assert(!std::is_copy_assignable_v); + + // Move properties + + static_assert(std::is_move_constructible_v); + static_assert(std::is_move_assignable_v); +} + +void test() { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif +} + +// Aliases + +static_assert(std::is_base_of_v, std::ispanstream>); +static_assert(std::is_same_v, std::ispanstream>); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::is_base_of_v, std::wispanstream>); +static_assert(std::is_same_v, std::wispanstream>); +#endif diff --git a/libcxx/test/std/input.output/span.streams/lit.local.cfg b/libcxx/test/std/input.output/span.streams/lit.local.cfg new file mode 100644 index 0000000000000..2cb10010c4507 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/lit.local.cfg @@ -0,0 +1,3 @@ +# All non-trivial uses of iostreams require localization support +if "no-localization" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/inherited.stream.ops.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/inherited.stream.ops.pass.cpp new file mode 100644 index 0000000000000..82be6cb7ac8bd --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/inherited.stream.ops.pass.cpp @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// Test stream operations inherited from `basic_ostream` + +#include +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "test_macros.h" + +#include "../helper_functions.h" +#include "../helper_macros.h" +#include "../helper_types.h" + +#include // REMOVE ME +#include // REMOVE ME + +template > +void test() { + using SpStream = std::basic_ospanstream; + + constexpr std::basic_string_view sv{SV("zmt 94 hkt 82 pir 43vr")}; + constexpr auto arrSize{30UZ}; + assert(sv.size() < arrSize); + + constexpr std::basic_string_view sv2{SV("This string should overflow! This string should overflow!")}; + assert(sv2.size() >= arrSize); + + // Create a std::span test value + CharT arr[arrSize]{}; + initialize_array_from_string_view(arr, sv); + std::span sp{arr}; + + // `std::span` + Mode: default (`out`) + { + // Construct stream + SpStream spSt(sp); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + assert(spSt.span().size() == 0); + + assert(arr[0] == CH('z')); // Check underlying buffer + assert(arr[1] == CH('m')); + assert(arr[2] == CH('t')); + + // Write to stream + spSt << SV("snt"); + + assert(spSt.span().size() == 3); + + assert(spSt.span()[0] == CH('s')); + assert(spSt.span()[1] == CH('n')); + assert(spSt.span()[2] == CH('t')); + + assert(arr[0] == CH('s')); // Check underlying buffer + assert(arr[1] == CH('n')); + assert(arr[2] == CH('t')); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + + spSt << 71; + + assert(spSt.span().size() == 5); + + assert(spSt.span()[3] == CH('7')); + assert(spSt.span()[4] == CH('1')); + + assert(arr[3] == CH('7')); // Check underlying buffer + assert(arr[4] == CH('1')); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + + spSt.put(CH('!')); + + assert(spSt.span().size() == 6); + + assert(spSt.span()[5] == CH('!')); + + assert(arr[5] == CH('!')); // Check underlying buffer + + spSt.write(CS("?#?"), 1); + + assert(spSt.span().size() == 7); + + assert(spSt.span()[6] == CH('?')); + + assert(arr[6] == CH('?')); // Check underlying buffer + + assert(spSt.tellp() == 7); + + // Write to stream with overflow + spSt << sv2; + + assert(spSt.span().size() == 30); + + assert(!spSt); + assert(spSt.bad()); + assert(spSt.fail()); + assert(!spSt.good()); + + // Test error state + assert(spSt.tellp() == -1); + + // Clear stream + spSt.clear(); + spSt.seekp(0); + + assert(spSt.span().size() == 0); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + // test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/assign.move.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/assign.move.pass.cpp new file mode 100644 index 0000000000000..c4b60631e67b3 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/assign.move.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { + +// // [spanstream.cons], constructors + +// basic_spanstream& operator=(basic_ospanstream&& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/ctor.move.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/ctor.move.pass.cpp new file mode 100644 index 0000000000000..f17b83e92797b --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/ctor.move.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { + +// // [spanstream.cons], constructors + +// basic_ospanstream(basic_ospanstream&& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/ctor.span.mode.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/ctor.span.mode.pass.cpp new file mode 100644 index 0000000000000..f0522059c5c5b --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.cons/ctor.span.mode.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { + +// // [spanstream.cons], constructors +// explicit basic_ospanstream(std::span s, +// ios_base::openmode which = ios_base::out | ios_base::in); + +#include +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_convertible.h" +#include "test_macros.h" + +#include "../../helper_types.h" + +template > +void test_sfinae() { + using SpStream = std::basic_ospanstream; + + // Mode + static_assert(std::constructible_from, std::ios_base::openmode>); + static_assert(!test_convertible, std::ios_base::openmode>()); + + // Non-mode + static_assert(!std::constructible_from, const NonMode>); + static_assert(!test_convertible, const NonMode>()); +} + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream spSt{sp}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + { + SpStream spSt{std::as_const(sp)}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode `out` + { + SpStream spSt{sp, std::ios_base::out}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + { + SpStream spSt{std::as_const(sp), std::ios_base::out}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode `ate` + { + SpStream spSt{sp, std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + { + SpStream spSt{std::as_const(sp), std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_sfinae(); +#endif + + test_sfinae(); + test_sfinae>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_sfinae(); + test_sfinae>(); +#endif + +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.general/lit.local.cfg b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.general/lit.local.cfg new file mode 100644 index 0000000000000..2cb10010c4507 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.general/lit.local.cfg @@ -0,0 +1,3 @@ +# All non-trivial uses of iostreams require localization support +if "no-localization" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.general/nothing_to_do.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.general/nothing_to_do.pass.cpp new file mode 100644 index 0000000000000..158afc6b33563 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.general/nothing_to_do.pass.cpp @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// [ospanstream.general] + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/rdbuf.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/rdbuf.pass.cpp new file mode 100644 index 0000000000000..dcb018ba6d50e --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/rdbuf.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { + +// // [ospanstream.members], members +// basic_spanbuf* rdbuf() const noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream spSt{sp}; + assert(spSt.rdbuf()->span().data() == arr); + // Mode `out` counts read characters + assert(spSt.rdbuf()->span().size() == 0); + } + // Mode: `out` + { + SpStream spSt{sp, std::ios_base::out}; + assert(spSt.rdbuf()->span().data() == arr); + // Mode `out` counts read characters + assert(spSt.rdbuf()->span().size() == 0); + } + // Mode: `ate` + { + SpStream spSt{sp, std::ios_base::ate}; + assert(spSt.rdbuf()->span().data() == arr); + assert(spSt.rdbuf()->span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/span.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/span.pass.cpp new file mode 100644 index 0000000000000..df04324f89287 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/span.pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { + +// // [ospanstream.members], members + +// std::span span() const noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(!sp.empty()); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream spSt{sp}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `out` + { + SpStream spSt{sp, std::ios_base::out}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream spSt{sp, std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/span.span.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/span.span.pass.cpp new file mode 100644 index 0000000000000..4567080b1ccf1 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.members/span.span.pass.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { + +// // [spanstream.members], members + +// void span(std::span s) noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(!sp.empty()); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `out` + { + SpStream spSt{std::span{}, std::ios_base::out}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream spSt{std::span{}, std::ios_base::ate}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode: multiple + { + SpStream spSt{std::span{}, std::ios_base::ate | std::ios_base::binary}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.swap/swap.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.swap/swap.pass.cpp new file mode 100644 index 0000000000000..94a36a29d508e --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.swap/swap.pass.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { + +// // [ospanstream.swap], swap +// void swap(basic_ospanstream& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.swap/swap_nonmember.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.swap/swap_nonmember.pass.cpp new file mode 100644 index 0000000000000..3e1c36848e692 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/ospanstream.swap/swap_nonmember.pass.cpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template +// void swap(basic_ospanstream& x, basic_ospanstream& y); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/ospanstream/types.compile.pass.cpp b/libcxx/test/std/input.output/span.streams/ospanstream/types.compile.pass.cpp new file mode 100644 index 0000000000000..d0d966521670f --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/ospanstream/types.compile.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_ospanstream +// : public basic_ostream { +// public: +// using char_type = charT; +// using int_type = typename traits::int_type; +// using pos_type = typename traits::pos_type; +// using off_type = typename traits::off_type; +// using traits_type = traits; + +// using ospanstream = basic_ospanstream; +// using wospanstream = basic_ospanstream; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_ospanstream; + + // Constructors + + static_assert(!std::is_default_constructible_v); + + // Types + + static_assert(std::is_base_of_v, SpStream>); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + // Copy properties + + static_assert(!std::is_copy_constructible_v); + static_assert(!std::is_copy_assignable_v); + + // Move properties + + static_assert(std::is_move_constructible_v); + static_assert(std::is_move_assignable_v); +} + +void test() { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif +} + +// Aliases + +static_assert(std::is_base_of_v, std::ospanstream>); +static_assert(std::is_same_v, std::ospanstream>); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::is_base_of_v, std::wospanstream>); +static_assert(std::is_same_v, std::wospanstream>); +#endif diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/assign.move.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/assign.move.pass.cpp new file mode 100644 index 0000000000000..b0d6cf68b01dd --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/assign.move.pass.cpp @@ -0,0 +1,331 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_streambuf { + +// // [spanbuf.cons], constructors +// +// basic_spanbuf& operator=(basic_spanbuf&& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template +struct TestSpanBuf : std::basic_spanbuf { + using std::basic_spanbuf::basic_spanbuf; + + TestSpanBuf(std::basic_spanbuf&& rhs_p) : std::basic_spanbuf(std::move(rhs_p)) {} + + void check_postconditions(TestSpanBuf const& rhs_p) const { + assert(this->span().data() == rhs_p.span().data()); + assert(this->span().size() == rhs_p.span().size()); + assert(this->eback() == rhs_p.eback()); + assert(this->gptr() == rhs_p.gptr()); + assert(this->egptr() == rhs_p.egptr()); + assert(this->pbase() == rhs_p.pbase()); + assert(this->pptr() == rhs_p.pptr()); + assert(this->epptr() == rhs_p.epptr()); + assert(this->getloc() == rhs_p.getloc()); + } +}; + +template > +void test_postconditions() { + using SpBuf = std::basic_spanbuf; + + // Empty `span` + { + // Mode: default (`in` | `out`) + { + std::span sp; + TestSpanBuf rhsSpBuf(sp); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `in` + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `out` + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: multiple + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in | std::ios_base::out | std::ios_base::binary); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `ate` + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out | std::ios_base::ate); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + } + + // Non-empty `span` + { + CharT arr[4]; + + // Mode: default (`in` | `out`) + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `in` + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `out` + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: multiple + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in | std::ios_base::out | std::ios_base::binary); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `ate` + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out | std::ios_base::ate); + TestSpanBuf spBuf = std::move(static_cast(rhsSpBuf)); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + } +} + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + // Empty `span` + { + // Mode: default (`in` | `out`) + { + SpBuf rhsSpBuf; + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf rhsSpBuf{std::ios_base::in}; + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `out` + { + SpBuf rhsSpBuf{std::ios_base::out}; + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{std::ios_base::ate}; + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: multiple + { + SpBuf rhsSpBuf{std::ios_base::out | std::ios_base::in | std::ios_base::ate}; + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + } + + // Non-empty `span` + { + CharT arr[4]; + std::span sp{arr}; + + // Mode: default (`in` | `out`) + { + SpBuf rhsSpBuf{sp}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf rhsSpBuf{sp, std::ios_base::in}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + // Mode `out` + { + SpBuf rhsSpBuf{sp, std::ios_base::out}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf = std::move(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + } + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_postconditions(); +#endif + test_postconditions(); + test_postconditions>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_postconditions(); + test_postconditions>(); +#endif + +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/swap.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/swap.pass.cpp new file mode 100644 index 0000000000000..432e0d70c5007 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/swap.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_spanbuf { + +// // [ispanstream.swap], swap +// void swap(basic_spanbuf& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpBuf rhsSpBuf{sp}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + spBuf.swap(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 0); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf rhsSpBuf{sp, std::ios_base::in}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf(std::span{}); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + spBuf.swap(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode `out` + { + SpBuf rhsSpBuf{sp, std::ios_base::out}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + spBuf.swap(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 0); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf(std::span{}); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + spBuf.swap(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf(std::span{}); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + spBuf.swap(rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/swap_nonmember.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/swap_nonmember.pass.cpp new file mode 100644 index 0000000000000..39b39f5a81764 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.assign/swap_nonmember.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template +// void swap(basic_spanbuf& x, basic_spanbuf& y); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(!sp.empty()); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpBuf rhsSpBuf{sp}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + std::swap(spBuf, rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 0); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf rhsSpBuf{sp, std::ios_base::in}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf(std::span{}); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + std::swap(spBuf, rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode `out` + { + SpBuf rhsSpBuf{sp, std::ios_base::out}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + std::swap(spBuf, rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 0); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf(std::span{}); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + std::swap(spBuf, rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf(std::span{}); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + std::swap(spBuf, rhsSpBuf); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/default.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/default.pass.cpp new file mode 100644 index 0000000000000..ef8c8d0b44642 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/default.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_streambuf { + +// // [spanbuf.cons], constructors +// basic_spanbuf(); + +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + { + SpBuf spBuf; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/mode.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/mode.pass.cpp new file mode 100644 index 0000000000000..4b45119e34014 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/mode.pass.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_streambuf { + +// // [spanbuf.cons], constructors +// +// explicit basic_spanbuf(ios_base::openmode which); + +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_convertible.h" +#include "test_macros.h" + +#include "../../helper_types.h" + +template > +void test_sfinae() { + using SpBuf = std::basic_spanbuf; + + // Mode + static_assert(std::constructible_from); + static_assert(!test_convertible()); + + // Non-mode + static_assert(!std::constructible_from); + static_assert(!test_convertible()); +} + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + // Mode: `in` + { + SpBuf spBuf{std::ios_base::in}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + // Mode: `out` + { + SpBuf spBuf{std::ios_base::out}; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf{std::ios_base::ate}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf{std::ios_base::out | std::ios_base::ate}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_sfinae(); +#endif + test_sfinae(); + test_sfinae>(); + +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_sfinae(); + test_sfinae>(); + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/move.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/move.pass.cpp new file mode 100644 index 0000000000000..f1eb1933e09c9 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/move.pass.cpp @@ -0,0 +1,336 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_streambuf { + +// // [spanbuf.cons], constructors +// +// basic_spanbuf(basic_spanbuf&& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template +struct TestSpanBuf : std::basic_spanbuf { + using std::basic_spanbuf::basic_spanbuf; + + TestSpanBuf(std::basic_spanbuf&& rhs_p) : std::basic_spanbuf(std::move(rhs_p)) {} + + void check_postconditions(TestSpanBuf const& rhs_p) const { + assert(this->span().data() == rhs_p.span().data()); + assert(this->span().size() == rhs_p.span().size()); + assert(this->eback() == rhs_p.eback()); + assert(this->gptr() == rhs_p.gptr()); + assert(this->egptr() == rhs_p.egptr()); + assert(this->pbase() == rhs_p.pbase()); + assert(this->pptr() == rhs_p.pptr()); + assert(this->epptr() == rhs_p.epptr()); + assert(this->getloc() == rhs_p.getloc()); + } +}; + +template > +void test_postconditions() { + using SpBuf = std::basic_spanbuf; + + // Empty `span` + { + // Mode: default + { + std::span sp; + TestSpanBuf rhsSpBuf(sp); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `in` + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `out` + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: multiple + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in | std::ios_base::out | std::ios_base::binary); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `ate` + { + std::span sp; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out | std::ios_base::ate); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == nullptr); + assert(spBuf.span().data() == nullptr); + spBuf.check_postconditions(rhsSpBuf); + } + } + + // Non-empty `span` + { + CharT arr[4]; + + // Mode: default + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `in` + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `out` + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: multiple + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::in | std::ios_base::out | std::ios_base::binary); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + // Mode: `ate` + { + std::span sp{arr}; + TestSpanBuf rhsSpBuf(sp, std::ios_base::out | std::ios_base::ate); + TestSpanBuf spBuf(std::move(static_cast(rhsSpBuf))); + assert(rhsSpBuf.span().data() == arr); + assert(spBuf.span().data() == arr); + spBuf.check_postconditions(rhsSpBuf); + } + } +} + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + // Empty `span` + { + // Mode: default (`in` | `out`) + { + SpBuf rhsSpBuf; + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf rhsSpBuf{std::ios_base::in}; + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == nullptr); + + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `out` + { + SpBuf rhsSpBuf{std::ios_base::out}; + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{std::ios_base::ate}; + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == nullptr); + + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: multiple + { + SpBuf rhsSpBuf{std::ios_base::out | std::ios_base::in | std::ios_base::ate}; + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == nullptr); + assert(rhsSpBuf.span().size() == 0); + } + } + + // Non-empty `span` + { + CharT arr[4]; + std::span sp{arr}; + + // Mode: default (`in` | `out`) + { + SpBuf rhsSpBuf{sp}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf rhsSpBuf{sp, std::ios_base::in}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + } + // Mode `out` + { + SpBuf rhsSpBuf{sp, std::ios_base::out}; + assert(rhsSpBuf.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpBuf.span().size() == 0); + + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + } + // Mode: `ate` + { + SpBuf rhsSpBuf{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + + SpBuf spBuf{std::move(rhsSpBuf)}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + // Test after move + assert(rhsSpBuf.span().data() == arr); + assert(rhsSpBuf.span().size() == 4); + } + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_postconditions(); +#endif + test_postconditions(); + test_postconditions>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_postconditions(); + test_postconditions>(); +#endif + +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/span.mode.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/span.mode.pass.cpp new file mode 100644 index 0000000000000..c33c741fd0707 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.cons/span.mode.pass.cpp @@ -0,0 +1,192 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_streambuf { + +// // [spanbuf.cons], constructors +// +// explicit basic_spanbuf(std::span s, +// ios_base::openmode which = ios_base::in | ios_base::out); + +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_convertible.h" +#include "test_macros.h" + +#include "../../helper_macros.h" +#include "../../helper_types.h" + +template > +void test_sfinae() { + using SpBuf = std::basic_spanbuf; + + // Mode + static_assert(std::constructible_from, std::ios_base::openmode>); + static_assert(!test_convertible, std::ios_base::openmode>()); + + // Non-mode + static_assert(!std::constructible_from, const NonMode>); + static_assert(!test_convertible, const NonMode>()); +} + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + // Empty `span` + { + std::span sp{}; + + // Mode: default (`in` | `out`) + { + SpBuf spBuf{sp}; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + { + SpBuf spBuf{std::as_const(sp)}; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf spBuf{sp, std::ios_base::in}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + { + SpBuf spBuf{std::as_const(sp), std::ios_base::in}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + // Mode: `out` + { + SpBuf spBuf{sp, std::ios_base::out}; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + { + SpBuf spBuf{std::as_const(sp), std::ios_base::out}; + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf{sp, std::ios_base::out | std::ios_base::ate}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + { + SpBuf spBuf{std::as_const(sp), std::ios_base::out | std::ios_base::ate}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + } + + // Non-empty `span` + { + CharT arr[4]; + std::span sp{arr}; + + // Mode: default (`in` | `out`) + { + SpBuf spBuf{sp}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + { + SpBuf spBuf{std::as_const(sp)}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf spBuf{sp, std::ios_base::in}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + { + SpBuf spBuf{std::as_const(sp), std::ios_base::in}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + // Mode `out` + { + SpBuf spBuf{sp, std::ios_base::out}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + { + SpBuf spBuf{std::as_const(sp), std::ios_base::out}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf{sp, std::ios_base::ate}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + { + SpBuf spBuf{std::as_const(sp), std::ios_base::ate}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + // Mode: `ate` + { + SpBuf spBuf{sp, std::ios_base::out | std::ios_base::ate}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + { + SpBuf spBuf{std::as_const(sp), std::ios_base::out | std::ios_base::ate}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_sfinae(); +#endif + test_sfinae(); + test_sfinae>(); +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_sfinae(); + test_sfinae>(); + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.general/lit.local.cfg b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.general/lit.local.cfg new file mode 100644 index 0000000000000..2cb10010c4507 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.general/lit.local.cfg @@ -0,0 +1,3 @@ +# All non-trivial uses of iostreams require localization support +if "no-localization" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.general/nothing_to_do.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.general/nothing_to_do.pass.cpp new file mode 100644 index 0000000000000..21fde6bfd26df --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.general/nothing_to_do.pass.cpp @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// [spanbuf.general] + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.members/span.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.members/span.pass.cpp new file mode 100644 index 0000000000000..df24aa877a4f5 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.members/span.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_spanbuf { + +// // [spanbuf.members], member functions +// std::span span() const noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpBuf spBuf(sp); + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf spBuf(sp, std::ios_base::in); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + // Mode: `out` + { + SpBuf spBuf(sp, std::ios_base::out); + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf(sp, std::ios_base::ate); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + // Mode: `ate` + { + SpBuf spBuf(sp, std::ios_base::out | std::ios_base::ate); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.members/span.span.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.members/span.span.pass.cpp new file mode 100644 index 0000000000000..a2c61a4b5f068 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.members/span.span.pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_spanbuf { + +// // [spanbuf.members], member functions +// +// void span(std::span s) noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpBuf spBuf; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + spBuf.span(arr); + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf spBuf{std::ios_base::in}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + spBuf.span(arr); + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + } + // Mode: `out` + { + SpBuf spBuf{std::ios_base::out}; + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + + spBuf.span(arr); + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf(std::ios_base::ate); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().empty()); + assert(spBuf.span().size() == 0); + + spBuf.span(arr); + assert(spBuf.span().data() == arr); + assert(!spBuf.span().empty()); + assert(spBuf.span().size() == 4); + } + // Mode: `ate` + { + SpBuf spBuf(std::ios_base::out | std::ios_base::ate); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().empty()); + assert(spBuf.span().size() == 0); + + spBuf.span(arr); + assert(spBuf.span().data() == arr); + assert(!spBuf.span().empty()); + assert(spBuf.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/seekoff.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/seekoff.pass.cpp new file mode 100644 index 0000000000000..b3b1b3a7dfb70 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/seekoff.pass.cpp @@ -0,0 +1,395 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_spanbuf { + +// // [spanbuf.virtuals], overridden virtual functions +// +// pos_type seekoff(off_type off, ios_base::seekdir way, +// ios_base::openmode which = ios_base::in | ios_base::out) override; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + constexpr auto no_mode = 0; + + // Empty `span` + { + std::span sp; + + // For an empty span: + // -3 is an out-of-range offset value + // 0 is an in-range offset value for an empty span + // 3 is an out-of-range offset value + + // Mode: default (`in` | `out`) + { + SpBuf spBuf{sp}; + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::in) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::out) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekoff(0, std::ios_base::beg) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(0, std::ios_base::end) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end) == -1); + + // No mode + assert(spBuf.pubseekoff(0, std::ios_base::beg, no_mode) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(0, std::ios_base::end, no_mode) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-1, std::ios_base::end, no_mode) == -1); + } + // Mode: `in` + { + SpBuf spBuf{sp, std::ios_base::in}; + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::in) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::out) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekoff(0, std::ios_base::beg) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur) == -1); // ??? + assert(spBuf.pubseekoff(0, std::ios_base::end) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end) == -1); + + // No mode + assert(spBuf.pubseekoff(0, std::ios_base::beg, no_mode) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(0, std::ios_base::end, no_mode) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, no_mode) == -1); + } + // Mode: `out` + { + SpBuf spBuf{sp, std::ios_base::out}; + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::in) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::out) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekoff(0, std::ios_base::beg) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur) == -1); // ??? + assert(spBuf.pubseekoff(0, std::ios_base::end) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end) == -1); + + // No mode + assert(spBuf.pubseekoff(0, std::ios_base::beg, no_mode) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(0, std::ios_base::end, no_mode) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, no_mode) == -1); + } + } + + // Non-empty `span` + { + CharT arr[10]; + std::span sp{arr}; + + // For an empty span: + // -999 is an out-of-range offset value + // 999 is an out-of-range offset value + + // Mode: default (`in` | `out`) + { + SpBuf spBuf{sp}; + + assert(spBuf.pubseekoff(-999, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(-999, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, std::ios_base::out) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, std::ios_base::out) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::in) == 10); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::in) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::in) == 6); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::in) == 7); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::out) == 10); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::out) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::out) == 6); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::out) == 7); + + // Default parameter value `openmode` + assert(spBuf.pubseekoff(-999, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur) == -1); // ??? + assert(spBuf.pubseekoff(0, std::ios_base::end) == 10); + + assert(spBuf.pubseekoff(3, std::ios_base::beg) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end) == 7); + + // No mode + assert(spBuf.pubseekoff(-999, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, no_mode) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, no_mode) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, no_mode) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(0, std::ios_base::end, no_mode) == 10); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg, no_mode) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, no_mode) == 7); + } + // Mode: `in` + { + SpBuf spBuf{sp, std::ios_base::in}; + + assert(spBuf.pubseekoff(-999, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(-999, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, std::ios_base::out) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, std::ios_base::out) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::in) == 10); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::in) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::in) == 6); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::in) == 7); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::out) == -1); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekoff(-999, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur) == -1); // ??? + assert(spBuf.pubseekoff(0, std::ios_base::end) == -1); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end) == -1); + + // No mode + assert(spBuf.pubseekoff(-999, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, no_mode) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, no_mode) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, no_mode) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(0, std::ios_base::end, no_mode) == 10); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg, no_mode) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, no_mode) == 7); + } + // Mode: `out` + { + SpBuf spBuf{sp, std::ios_base::out}; + + assert(spBuf.pubseekoff(-999, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(-999, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, std::ios_base::out) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, std::ios_base::out) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, std::ios_base::out) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::in) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::in) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::in) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::in) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, std::ios_base::out) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::end, std::ios_base::out) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg, std::ios_base::out) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur, std::ios_base::out) == 6); + assert(spBuf.pubseekoff(-3, std::ios_base::end, std::ios_base::out) == 3); + + // Default parameter value `openmode` + assert(spBuf.pubseekoff(-999, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur) == -1); // ??? + assert(spBuf.pubseekoff(0, std::ios_base::end) == 0); + + assert(spBuf.pubseekoff(3, std::ios_base::beg) == -1); + assert(spBuf.pubseekoff(3, std::ios_base::cur) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end) == -1); + + // No mode + assert(spBuf.pubseekoff(-999, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-999, std::ios_base::end, no_mode) == -1); + + assert(spBuf.pubseekoff(999, std::ios_base::beg, no_mode) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(999, std::ios_base::end, no_mode) == -1); + + assert(spBuf.pubseekoff(0, std::ios_base::beg, no_mode) == 0); + assert(spBuf.pubseekoff(0, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(0, std::ios_base::end, no_mode) == 0); // ??? + + assert(spBuf.pubseekoff(3, std::ios_base::beg, no_mode) == 3); + assert(spBuf.pubseekoff(3, std::ios_base::cur, no_mode) == -1); + assert(spBuf.pubseekoff(-3, std::ios_base::end, no_mode) == -1); // ??? + } + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/seekpos.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/seekpos.pass.cpp new file mode 100644 index 0000000000000..eae307a769bfc --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/seekpos.pass.cpp @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_spanbuf { + +// // [spanbuf.virtuals], overridden virtual functions +// +// pos_type seekpos(pos_type sp, +// ios_base::openmode which = ios_base::in | ios_base::out) override; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +// `seekpos` is the same as `seekoff` with `ios_base::beg` +template > +void test() { + using SpBuf = std::basic_spanbuf; + + constexpr auto no_mode = 0; + + // Empty `span` + { + std::span sp; + + // For an empty span: + // 0 is an in-range offset value for an empty span + // 3 is an out-of-range offset value + + // Mode: default (`in` | `out`) + { + SpBuf spBuf{sp}; + + assert(spBuf.pubseekpos(0, std::ios_base::in) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::in) == -1); + + assert(spBuf.pubseekpos(0, std::ios_base::out) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekpos(0) == 0); + assert(spBuf.pubseekpos(3) == -1); + + // No mode + assert(spBuf.pubseekpos(0, no_mode) == 0); + assert(spBuf.pubseekpos(3, no_mode) == -1); + } + // Mode: `in` + { + SpBuf spBuf{sp, std::ios_base::in}; + + assert(spBuf.pubseekpos(0, std::ios_base::in) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::in) == -1); + + assert(spBuf.pubseekpos(0, std::ios_base::out) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekpos(0) == 0); + assert(spBuf.pubseekpos(3) == -1); + + // No mode + assert(spBuf.pubseekpos(0, no_mode) == 0); + assert(spBuf.pubseekpos(3, no_mode) == -1); + } + // Mode: `out` + { + SpBuf spBuf{sp, std::ios_base::out}; + + assert(spBuf.pubseekpos(0, std::ios_base::in) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::in) == -1); + + assert(spBuf.pubseekpos(0, std::ios_base::out) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekpos(0) == 0); + assert(spBuf.pubseekpos(3) == -1); + + // No mode + assert(spBuf.pubseekpos(0, no_mode) == 0); + assert(spBuf.pubseekpos(3, no_mode) == -1); + } + } + + // Non-empty `span` + { + CharT arr[10]; + std::span sp{arr}; + + // For an empty span: + // 999 is an out-of-range offset value + + // Mode: default (`in` | `out`) + { + SpBuf spBuf{sp}; + + assert(spBuf.pubseekpos(999, std::ios_base::in) == -1); + + assert(spBuf.pubseekpos(999, std::ios_base::out) == -1); + + assert(spBuf.pubseekpos(0, std::ios_base::in) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::in) == 3); + + assert(spBuf.pubseekpos(0, std::ios_base::out) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::out) == 3); + + // Default parameter value `openmode` + assert(spBuf.pubseekpos(999) == -1); + + assert(spBuf.pubseekpos(0) == 0); + assert(spBuf.pubseekpos(3) == 3); + + // No mode + assert(spBuf.pubseekpos(-999, no_mode) == -1); + assert(spBuf.pubseekpos(999, no_mode) == -1); + + assert(spBuf.pubseekpos(0, no_mode) == 0); + assert(spBuf.pubseekpos(3, no_mode) == 3); + } + // Mode: `in` + { + SpBuf spBuf{sp, std::ios_base::in}; + + assert(spBuf.pubseekpos(999, std::ios_base::in) == -1); + + assert(spBuf.pubseekpos(999, std::ios_base::out) == -1); + + assert(spBuf.pubseekpos(0, std::ios_base::in) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::in) == 3); + + assert(spBuf.pubseekpos(0, std::ios_base::out) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::out) == -1); + + // Default parameter value `openmode` + assert(spBuf.pubseekpos(999) == -1); + + assert(spBuf.pubseekpos(0) == 0); + assert(spBuf.pubseekpos(3) == -1); + + // No mode + assert(spBuf.pubseekpos(999, no_mode) == -1); + + assert(spBuf.pubseekpos(0, no_mode) == 0); + assert(spBuf.pubseekpos(3, no_mode) == 3); + } + // Mode: `out` + { + SpBuf spBuf{sp, std::ios_base::out}; + + assert(spBuf.pubseekpos(999, std::ios_base::in) == -1); + + assert(spBuf.pubseekpos(999, std::ios_base::out) == -1); + + assert(spBuf.pubseekpos(0, std::ios_base::in) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::in) == -1); + + assert(spBuf.pubseekpos(0, std::ios_base::out) == 0); + assert(spBuf.pubseekpos(3, std::ios_base::out) == 3); + + // Default parameter value `openmode` + assert(spBuf.pubseekpos(999) == -1); + assert(spBuf.pubseekpos(0) == 0); + assert(spBuf.pubseekpos(3) == -1); + + // No mode + assert(spBuf.pubseekpos(999, no_mode) == -1); + assert(spBuf.pubseekpos(0, no_mode) == 0); + assert(spBuf.pubseekpos(3, no_mode) == 3); + } + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/setbuf.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/setbuf.pass.cpp new file mode 100644 index 0000000000000..fb6c6bbb6bdec --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/spanbuf.virtuals/setbuf.pass.cpp @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_spanbuf { + +// // [spanbuf.virtuals], overridden virtual functions +// basic_streambuf* setbuf(charT*, streamsize) override; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + CharT arr[4]; + std::span sp{arr}; + + // Mode: default (`in` | `out`) + { + SpBuf spBuf{sp}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + spBuf.pubsetbuf(nullptr, 0); + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `in` + { + SpBuf spBuf{sp, std::ios_base::in}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + spBuf.pubsetbuf(nullptr, 0); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + // Mode `out` + { + SpBuf spBuf{sp, std::ios_base::out}; + assert(spBuf.span().data() == arr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + + spBuf.pubsetbuf(nullptr, 0); + assert(spBuf.span().data() == nullptr); + // Mode `out` counts read characters + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf{sp, std::ios_base::ate}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + spBuf.pubsetbuf(nullptr, 0); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } + // Mode: `ate` + { + SpBuf spBuf{sp, std::ios_base::out | std::ios_base::ate}; + assert(spBuf.span().data() == arr); + assert(spBuf.span().size() == 4); + + spBuf.pubsetbuf(nullptr, 0); + assert(spBuf.span().data() == nullptr); + assert(spBuf.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanbuf/types.compile.pass.cpp b/libcxx/test/std/input.output/span.streams/spanbuf/types.compile.pass.cpp new file mode 100644 index 0000000000000..dbed1792b7ab0 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanbuf/types.compile.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanbuf +// : public basic_streambuf { +// public: +// using char_type = charT; +// using int_type = typename traits::int_type; +// using pos_type = typename traits::pos_type; +// using off_type = typename traits::off_type; +// using traits_type = traits; + +// using spanbuf = basic_spanbufchar>; +// using wspanbuf = basic_spanbuf; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpBuf = std::basic_spanbuf; + + // Constructors + + static_assert(std::is_default_constructible_v); + + // Types + + static_assert(std::is_base_of_v, SpBuf>); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + // Copy properties + + static_assert(!std::is_copy_constructible_v); + static_assert(!std::is_copy_assignable_v); + + // Move properties + + static_assert(std::is_move_constructible_v); + static_assert(std::is_move_assignable_v); +} + +void test() { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif +} + +// Aliases + +static_assert(std::is_base_of_v, std::spanbuf>); +static_assert(std::is_same_v, std::spanbuf>); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::is_base_of_v, std::wspanbuf>); +static_assert(std::is_same_v, std::wspanbuf>); +#endif diff --git a/libcxx/test/std/input.output/span.streams/spanstream/inherited.stream.ops.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/inherited.stream.ops.pass.cpp new file mode 100644 index 0000000000000..8e2b74b25ed58 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/inherited.stream.ops.pass.cpp @@ -0,0 +1,308 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// Test stream operations inherited from `basic_istream` and `basic_ostream` + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +#include "../helper_macros.h" + +template > +void initialize_array(CharT* arr, std::basic_string_view sv) { + if constexpr (std::same_as) + strncpy(arr, sv.data(), sv.size() + 1); + else + wcsncpy(arr, sv.data(), sv.size() + 1); +} + +template > +void test() { + using SpStream = std::basic_spanstream; + + constexpr auto arrSize{30UZ}; + + constexpr std::basic_string_view sv{SV("zmt 94 hkt 82 pir 43vr")}; + assert(sv.size() < arrSize); + + CharT arr[arrSize]{}; + initialize_array(arr, sv); + + std::span sp{arr}; + + // Mode: default (`in` | `out`) + { + SpStream spSt(sp); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + assert(spSt.span().size() == 0); + + // Read from stream + std::basic_string str1; + spSt >> str1; + int i1; + spSt >> i1; + std::basic_string str2; + spSt >> str2; + int i2; + spSt >> i2; + std::basic_string str3; + spSt >> str3; + int i3; + spSt >> i3; + + assert(str1 == CS("zmt")); + assert(i1 == 94); + assert(str2 == CS("hkt")); + assert(i2 == 82); + assert(str3 == CS("pir")); + assert(i3 == 43); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + + // Write to stream + constexpr std::basic_string_view sv1{SV("year 2024")}; + spSt << sv1; + + assert(spSt.span().size() == sv1.size()); + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + + // Read from stream + spSt.seekg(0); + std::basic_string str4; + spSt >> str4; + int i4; + spSt >> i4; + + assert(str4 == CS("year")); + assert(i4 == 2024); + + spSt >> i4; + + assert(!spSt); + assert(!spSt.bad()); + assert(spSt.fail()); + assert(!spSt.good()); + + spSt.clear(); + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + + // Write to stream + spSt << CS("94"); + spSt << 84; + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + + assert(spSt.span().size() == sv1.size() + 4); + std::basic_string expectedStr1{spSt.span().data(), std::size_t{spSt.span().size()}}; + assert(expectedStr1 == CS("year 20249484")); + + // Write to stream with overflow + constexpr std::basic_string_view sv2{ + SV("This string should overflow! This string should overflow!")}; + spSt << sv2; + assert(spSt.span().size() == arrSize); + std::basic_string expectedStr2{spSt.span().data(), std::size_t{spSt.span().size()}}; + assert(expectedStr2 == CS("year 20249484This string shoul")); + + assert(!spSt); + assert(spSt.bad()); + assert(spSt.fail()); + assert(!spSt.good()); + } +#if 0 + // Mode: `in` + { + SpStream spSt{sp, std::ios_base::in}; + assert(spSt); + assert(spSt.good()); + assert(spSt.span().size() == arrSize); + + std::basic_string expectedStr0{spSt.span().data(), std::size_t{spSt.span().size()}}; + std::cout << expectedStr0 << std::endl; + + // // Read from stream + // std::basic_string str1; + // spSt >> str1; + // int i1; + // spSt >> i1; + // std::basic_string str2; + // spSt >> str2; + // int i2; + // spSt >> i2; + // std::basic_string str3; + // spSt >> str3; + // int i3; + // spSt >> i3; + + // assert(spSt.good()); + // assert(str1 == CS("zmt")); + // assert(i1 == 94); + // assert(str2 == CS("hkt")); + // assert(i2 == 82); + // assert(str3 == CS("pir")); + // assert(i3 == 43); + + // Write to stream + constexpr std::basic_string_view sv1{SV("year 2024")}; + spSt << sv1; + + std::cout << spSt.span().size() << std::endl; + assert(spSt.span().size() == sv1.size()); + assert(spSt.good()); + + // Read from stream + spSt.seekg(0); + std::basic_string str4; + spSt >> str4; + int i4; + spSt >> i4; + + assert(str4 == CS("year")); + assert(i4 == 2024); + + spSt >> i4; + assert(spSt); + assert(!spSt.bad()); + assert(spSt.fail()); + assert(!spSt.good()); + + spSt.clear(); + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); + // Write to stream + spSt << CS("94"); + spSt << 84; + + assert(spSt); + assert(!spSt.bad()); + assert(!spSt.fail()); + assert(spSt.good()); assert(spSt.span().size() == sv1.size() + 4); + std::basic_string expectedStr1{spSt.span().data(), std::size_t{spSt.span().size()}}; + assert(expectedStr1 == CS("year 20249484")); + + // Write to stream with overflow + constexpr std::basic_string_view sv2{ + SV("This string should overflow! This string should overflow!")}; + spSt << sv2; + assert(spSt.span().size() == arrSize); + std::basic_string expectedStr2{spSt.span().data(), std::size_t{spSt.span().size()}}; + assert(expectedStr2 == CS("year 20249484This string shoul")); + assert(spSt); + assert(!spSt.bad()); + assert(spSt.fail()); + assert(!spSt.good()); } + // Mode `out` + { + SpStream spSt{sp, std::ios_base::out}; + assert(spSt.span().size() == 0); + + // Read from stream + std::basic_string str1; + spSt >> str1; + int i1; + spSt >> i1; + std::basic_string str2; + spSt >> str2; + int i2; + spSt >> i2; + std::basic_string str3; + spSt >> str3; + int i3; + spSt >> i3; + + assert(spSt.good()); + assert(str1 == CS("zmt")); + assert(i1 == 94); + assert(str2 == CS("hkt")); + assert(i2 == 82); + assert(str3 == CS("pir")); + assert(i3 == 43); + + // Write to stream + constexpr std::basic_string_view sv1{SV("year 2024")}; + spSt << sv1; + + assert(spSt.span().size() == sv1.size()); + assert(spSt.good()); + + // Read from stream + spSt.seekg(0); + std::basic_string str4; + spSt >> str4; + int i4; + spSt >> i4; + + assert(str4 == CS("year")); + assert(i4 == 2024); + + spSt >> i4; + assert(spSt.fail()); + spSt.clear(); + assert(spSt.good()); + + // Write to stream + spSt << CS("94"); + spSt << 84; + + assert(spSt.good()); + assert(spSt.span().size() == sv1.size() + 4); + std::basic_string expectedStr1{spSt.span().data(), std::size_t{spSt.span().size()}}; + assert(expectedStr1 == CS("year 20249484")); + + // Write to stream with overflow + constexpr std::basic_string_view sv2{ + SV("This string should overflow! This string should overflow!")}; + spSt << sv2; + assert(spSt.span().size() == arrSize); + std::basic_string expectedStr2{spSt.span().data(), std::size_t{spSt.span().size()}}; + assert(expectedStr2 == CS("year 20249484This string shoul")); + assert(spSt.fail()); + } +#endif +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/assign.move.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/assign.move.pass.cpp new file mode 100644 index 0000000000000..2fdb6869e22a0 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/assign.move.pass.cpp @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// // [spanstream.cons], constructors + +// basic_spanstream& operator=(basic_spanstream&& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } + // Mode `ate` + { + SpStream rhsSpSt{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt = std::move(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/ctor.move.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/ctor.move.pass.cpp new file mode 100644 index 0000000000000..589b3af943026 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/ctor.move.pass.cpp @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// // [spanstream.cons], constructors + +// basic_spanstream(basic_spanstream&& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } + // Mode `ate` + { + SpStream rhsSpSt{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt{std::move(rhsSpSt)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + + // Test after move + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/ctor.span.mode.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/ctor.span.mode.pass.cpp new file mode 100644 index 0000000000000..b766266bc03bc --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.cons/ctor.span.mode.pass.cpp @@ -0,0 +1,135 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// // [spanstream.cons], constructors +// explicit basic_spanstream(std::span s, +// ios_base::openmode which = ios_base::out | ios_base::in); + +#include +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_convertible.h" +#include "test_macros.h" + +#include "../../helper_types.h" + +template > +void test_sfinae() { + using SpStream = std::basic_spanstream; + + // Mode + static_assert(std::constructible_from, std::ios_base::openmode>); + static_assert(!test_convertible, std::ios_base::openmode>()); + + // Non-mode + static_assert(!std::constructible_from, const NonMode>); + static_assert(!test_convertible, const NonMode>()); +} + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream spSt{sp}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + } + { + SpStream spSt{std::as_const(sp)}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + } + // Mode: `in` + { + SpStream spSt{sp, std::ios_base::in}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + { + SpStream spSt{std::as_const(sp), std::ios_base::in}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode `out` + { + SpStream spSt{sp, std::ios_base::out}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + } + { + SpStream spSt{std::as_const(sp), std::ios_base::out}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + } + // Mode `ate` + { + SpStream spSt{sp, std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + { + SpStream spSt{std::as_const(sp), std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode `ate` + { + SpStream spSt{sp, std::ios_base::out | std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + { + SpStream spSt{std::as_const(sp), std::ios_base::out | std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test_sfinae(); +#endif + test_sfinae(); + test_sfinae>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test_sfinae(); + test_sfinae>(); +#endif + +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.general/lit.local.cfg b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.general/lit.local.cfg new file mode 100644 index 0000000000000..2cb10010c4507 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.general/lit.local.cfg @@ -0,0 +1,3 @@ +# All non-trivial uses of iostreams require localization support +if "no-localization" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.general/nothing_to_do.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.general/nothing_to_do.pass.cpp new file mode 100644 index 0000000000000..db651e1bd900c --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.general/nothing_to_do.pass.cpp @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// [spanstream.general] + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/rdbuf.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/rdbuf.pass.cpp new file mode 100644 index 0000000000000..3e4ecb67224d4 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/rdbuf.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// // [spanstream.members], members +// basic_spanbuf* rdbuf() const noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream spSt{sp}; + assert(spSt.rdbuf()->span().data() == arr); + // Mode `out` counts read characters + assert(spSt.rdbuf()->span().size() == 0); + } + // Mode: `in` + { + SpStream spSt{sp, std::ios_base::in}; + assert(spSt.rdbuf()->span().data() == arr); + assert(spSt.rdbuf()->span().size() == 4); + } + // Mode: `out` + { + SpStream spSt{sp, std::ios_base::out}; + assert(spSt.rdbuf()->span().data() == arr); + // Mode `out` counts read characters + assert(spSt.rdbuf()->span().size() == 0); + } + // Mode: `ate` + { + SpStream spSt{sp, std::ios_base::ate}; + assert(spSt.rdbuf()->span().data() == arr); + assert(spSt.rdbuf()->span().size() == 4); + } + // Mode: `ate` + { + SpStream spSt{sp, std::ios_base::out | std::ios_base::ate}; + assert(spSt.rdbuf()->span().data() == arr); + assert(spSt.rdbuf()->span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/span.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/span.pass.cpp new file mode 100644 index 0000000000000..b23e411b99230 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/span.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// // [spanstream.members], members + +// std::span span() const noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(!sp.empty()); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream spSt{sp}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `in` + { + SpStream spSt{sp, std::ios_base::in}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode: `out` + { + SpStream spSt{sp, std::ios_base::out}; + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream spSt{sp, std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode: `ate` + { + SpStream spSt{sp, std::ios_base::out | std::ios_base::ate}; + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/span.span.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/span.span.pass.cpp new file mode 100644 index 0000000000000..41477f3eaebf7 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.members/span.span.pass.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// // [spanstream.members], members + +// void span(std::span s) noexcept; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `in` + { + SpStream spSt{std::span{}, std::ios_base::in}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode: `out` + { + SpStream spSt{std::span{}, std::ios_base::out}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream spSt{std::span{}, std::ios_base::ate}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } + // Mode: `ate` + { + SpStream spSt{std::span{}, std::ios_base::out | std::ios_base::ate}; + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.span(arr); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.swap/swap.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.swap/swap.pass.cpp new file mode 100644 index 0000000000000..389023912d3cd --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.swap/swap.pass.cpp @@ -0,0 +1,135 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { + +// // [spanstream.swap], swap +// void swap(basic_spanstream& rhs); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream rhsSpSt{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + spSt.swap(rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/spanstream.swap/swap_nonmember.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.swap/swap_nonmember.pass.cpp new file mode 100644 index 0000000000000..0eeada5f3bc8c --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/spanstream.swap/swap_nonmember.pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template +// void swap(basic_spanstream& x, basic_spanstream& y); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + CharT arr[4]; + + std::span sp{arr}; + assert(sp.data() == arr); + assert(sp.size() == 4); + + // Mode: default (`in` | `out`) + { + SpStream rhsSpSt{sp}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `in` + { + SpStream rhsSpSt{sp, std::ios_base::in}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode `out` + { + SpStream rhsSpSt{sp, std::ios_base::out}; + assert(rhsSpSt.span().data() == arr); + // Mode `out` counts read characters + assert(rhsSpSt.span().size() == 0); + + SpStream spSt{std::span{}}; + assert(spSt.span().data() == nullptr); + // Mode `out` counts read characters + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 0); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream rhsSpSt{sp, std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().empty()); + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } + // Mode: `ate` + { + SpStream rhsSpSt{sp, std::ios_base::out | std::ios_base::ate}; + assert(rhsSpSt.span().data() == arr); + assert(rhsSpSt.span().size() == 4); + + SpStream spSt(std::span{}); + assert(spSt.span().data() == nullptr); + assert(spSt.span().empty()); + assert(spSt.span().size() == 0); + + std::swap(spSt, rhsSpSt); + assert(spSt.span().data() == arr); + assert(spSt.span().size() == 4); + assert(rhsSpSt.span().data() == nullptr); + assert(rhsSpSt.span().size() == 0); + } +} + +int main(int, char**) { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/span.streams/spanstream/types.compile.pass.cpp b/libcxx/test/std/input.output/span.streams/spanstream/types.compile.pass.cpp new file mode 100644 index 0000000000000..6562841558463 --- /dev/null +++ b/libcxx/test/std/input.output/span.streams/spanstream/types.compile.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// + +// template> +// class basic_spanstream +// : public basic_iostream { +// public: +// using char_type = charT; +// using int_type = typename traits::int_type; +// using pos_type = typename traits::pos_type; +// using off_type = typename traits::off_type; +// using traits_type = traits; + +// using spanstream = basic_spanstream; +// using wspanstream = basic_spanstream; + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "nasty_string.h" +#include "test_macros.h" + +template > +void test() { + using SpStream = std::basic_spanstream; + + // Constructors + + static_assert(!std::is_default_constructible_v); + + // Types + + static_assert(std::is_base_of_v, SpStream>); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + // Copy properties + + static_assert(!std::is_copy_constructible_v); + static_assert(!std::is_copy_assignable_v); + + // Move properties + + static_assert(std::is_move_constructible_v); + static_assert(std::is_move_assignable_v); +} + +void test() { +#ifndef TEST_HAS_NO_NASTY_STRING + test(); +#endif + test(); + test>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + test>(); +#endif +} + +// Aliases + +static_assert(std::is_base_of_v, std::spanstream>); +static_assert(std::is_same_v, std::spanstream>); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::is_base_of_v, std::wspanstream>); +static_assert(std::is_same_v, std::wspanstream>); +#endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/spanstream.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/spanstream.version.compile.pass.cpp new file mode 100644 index 0000000000000..8ab394d8168ac --- /dev/null +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/spanstream.version.compile.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// WARNING: This test was generated by generate_feature_test_macro_components.py +// and should not be edited manually. + +// UNSUPPORTED: no-localization + +// + +// Test the feature test macros defined by + +// clang-format off + +#include +#include "test_macros.h" + +#if TEST_STD_VER < 14 + +# ifdef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should not be defined before c++23" +# endif + +#elif TEST_STD_VER == 14 + +# ifdef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should not be defined before c++23" +# endif + +#elif TEST_STD_VER == 17 + +# ifdef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should not be defined before c++23" +# endif + +#elif TEST_STD_VER == 20 + +# ifdef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should not be defined before c++23" +# endif + +#elif TEST_STD_VER == 23 + +# ifndef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should be defined in c++23" +# endif +# if __cpp_lib_spanstream != 202106L +# error "__cpp_lib_spanstream should have the value 202106L in c++23" +# endif + +#elif TEST_STD_VER > 23 + +# ifndef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should be defined in c++26" +# endif +# if __cpp_lib_spanstream != 202106L +# error "__cpp_lib_spanstream should have the value 202106L in c++26" +# endif + +#endif // TEST_STD_VER > 23 + +// clang-format on diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index 962688e06188a..49c9f7df71602 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -5913,17 +5913,11 @@ # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_spanstream -# error "__cpp_lib_spanstream should be defined in c++23" -# endif -# if __cpp_lib_spanstream != 202106L -# error "__cpp_lib_spanstream should have the value 202106L in c++23" -# endif -# else -# ifdef __cpp_lib_spanstream -# error "__cpp_lib_spanstream should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should be defined in c++23" +# endif +# if __cpp_lib_spanstream != 202106L +# error "__cpp_lib_spanstream should have the value 202106L in c++23" # endif # ifndef __cpp_lib_ssize @@ -7879,17 +7873,11 @@ # error "__cpp_lib_span_initializer_list should have the value 202311L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_spanstream -# error "__cpp_lib_spanstream should be defined in c++26" -# endif -# if __cpp_lib_spanstream != 202106L -# error "__cpp_lib_spanstream should have the value 202106L in c++26" -# endif -# else -# ifdef __cpp_lib_spanstream -# error "__cpp_lib_spanstream should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_spanstream +# error "__cpp_lib_spanstream should be defined in c++26" +# endif +# if __cpp_lib_spanstream != 202106L +# error "__cpp_lib_spanstream should have the value 202106L in c++26" # endif # ifndef __cpp_lib_ssize diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index fe175fd758726..bf9508e36410a 100644 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -1297,7 +1297,6 @@ def add_version_header(tc): "name": "__cpp_lib_spanstream", "values": {"c++23": 202106}, "headers": ["spanstream"], - "unimplemented": True, }, { "name": "__cpp_lib_ssize", @@ -1515,6 +1514,7 @@ def add_version_header(tc): "regex": ["UNSUPPORTED: no-localization"], "semaphore": ["UNSUPPORTED: no-threads"], "shared_mutex": ["UNSUPPORTED: no-threads"], + "spanstream": ["UNSUPPORTED: no-localization"], "sstream": ["UNSUPPORTED: no-localization"], "syncstream": ["UNSUPPORTED: no-localization"], "stdatomic.h": ["UNSUPPORTED: no-threads"], diff --git a/libcxx/utils/generate_iwyu_mapping.py b/libcxx/utils/generate_iwyu_mapping.py index ab3e3f14e14d8..c92fecda3daf0 100644 --- a/libcxx/utils/generate_iwyu_mapping.py +++ b/libcxx/utils/generate_iwyu_mapping.py @@ -47,7 +47,9 @@ def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]: return ["utility"] elif header == "__fwd/subrange.h": return ["ranges"] - elif re.match("__fwd/(fstream|ios|istream|ostream|sstream|streambuf)[.]h", header): + elif re.match( + "__fwd/(fstream|ios|istream|ostream|spanstream|sstream|streambuf)[.]h", header + ): return ["iosfwd"] # Handle remaining forward declaration headers elif re.match("__fwd/(.+)[.]h", header): diff --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py index d06271a7908cc..e6a8fd53a1e0a 100644 --- a/libcxx/utils/libcxx/header_information.py +++ b/libcxx/utils/libcxx/header_information.py @@ -169,7 +169,6 @@ def __hash__(self) -> int: "inplace_vector", "linalg", "rcu", - "spanstream", "stacktrace", "stdfloat", "text_encoding",