| // Streams based on std::span -*- C++ -*- |
| |
| // Copyright The GNU Toolchain Authors. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // Under Section 7 of GPL version 3, you are granted additional |
| // permissions described in the GCC Runtime Library Exception, version |
| // 3.1, as published by the Free Software Foundation. |
| |
| // You should have received a copy of the GNU General Public License and |
| // a copy of the GCC Runtime Library Exception along with this program; |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| // <http://www.gnu.org/licenses/>. |
| |
| /** @file spanstream |
| * This is a Standard C++ Library header. |
| */ |
| |
| #ifndef _GLIBCXX_SPANSTREAM |
| #define _GLIBCXX_SPANSTREAM 1 |
| |
| #pragma GCC system_header |
| |
| #include <bits/requires_hosted.h> // iostreams |
| |
| #if __cplusplus > 202002L |
| #include <span> |
| #include <streambuf> |
| #include <istream> |
| #include <ostream> |
| #include <bits/ranges_base.h> |
| |
| #if __cpp_lib_span |
| namespace std _GLIBCXX_VISIBILITY(default) |
| { |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION |
| |
| #define __cpp_lib_spanstream 202106L |
| |
| template<typename _CharT, typename _Traits> |
| class basic_spanbuf |
| : public basic_streambuf<_CharT, _Traits> |
| { |
| using __streambuf_type = 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.ctor], constructors |
| basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out) |
| { } |
| |
| explicit |
| basic_spanbuf(ios_base::openmode __which) |
| : __streambuf_type(), _M_mode(__which) |
| { } |
| |
| explicit |
| basic_spanbuf(std::span<_CharT> __s, |
| ios_base::openmode __which = ios_base::in | ios_base::out) |
| : __streambuf_type(), _M_mode(__which) |
| { span(__s); } |
| |
| basic_spanbuf(const basic_spanbuf&) = delete; |
| |
| /** Move constructor. |
| * |
| * Transfers the buffer and pointers into the get and put areas from |
| * `__rhs` to `*this`. |
| * |
| * In this implementation `rhs` is left unchanged, |
| * but that is not guaranteed by the standard. |
| */ |
| basic_spanbuf(basic_spanbuf&& __rhs) |
| : __streambuf_type(__rhs), _M_mode(__rhs._M_mode), _M_buf(__rhs._M_buf) |
| { } |
| |
| // [spanbuf.assign], assignment and swap |
| basic_spanbuf& operator=(const basic_spanbuf&) = delete; |
| |
| basic_spanbuf& |
| operator=(basic_spanbuf&& __rhs) |
| { |
| basic_spanbuf(std::move(__rhs)).swap(*this); |
| return *this; |
| } |
| |
| void |
| swap(basic_spanbuf& __rhs) |
| { |
| __streambuf_type::swap(__rhs); |
| std::swap(_M_mode, __rhs._M_mode); |
| std::swap(_M_buf, __rhs._M_buf); |
| } |
| |
| // [spanbuf.members], member functions |
| std::span<_CharT> |
| span() const noexcept |
| { |
| if (_M_mode & ios_base::out) |
| return {this->pbase(), this->pptr()}; |
| else |
| return _M_buf; |
| } |
| |
| void |
| span(std::span<_CharT> __s) noexcept |
| { |
| _M_buf = __s; |
| if (_M_mode & ios_base::out) |
| { |
| this->setp(__s.data(), __s.data() + __s.size()); |
| if (_M_mode & ios_base::ate) |
| this->pbump(__s.size()); |
| } |
| if (_M_mode & ios_base::in) |
| this->setg(__s.data(), __s.data(), __s.data() + __s.size()); |
| } |
| |
| protected: |
| // [spanbuf.virtuals], overridden virtual functions |
| basic_streambuf<_CharT, _Traits>* |
| setbuf(_CharT* __s, streamsize __n) override |
| { |
| __glibcxx_assert(__n >= 0); |
| this->span(std::span<_CharT>(__s, __n)); |
| return this; |
| } |
| |
| pos_type |
| seekoff(off_type __off, ios_base::seekdir __way, |
| ios_base::openmode __which = ios_base::in | ios_base::out) override |
| { |
| pos_type __ret = pos_type(off_type(-1)); |
| |
| if (__way == ios_base::beg) |
| { |
| if (0 <= __off && __off <= _M_buf.size()) |
| { |
| if (__which & ios_base::in) |
| this->setg(this->eback(), this->eback() + __off, this->egptr()); |
| |
| if (__which & ios_base::out) |
| { |
| this->setp(this->pbase(), this->epptr()); |
| this->pbump(__off); |
| } |
| |
| __ret = pos_type(__off); |
| } |
| } |
| else |
| { |
| off_type __base; |
| __which &= (ios_base::in|ios_base::out); |
| |
| if (__which == ios_base::out) |
| __base = this->pptr() - this->pbase(); |
| else if (__way == ios_base::cur) |
| { |
| if (__which == ios_base::in) |
| __base = this->gptr() - this->eback(); |
| else |
| return __ret; |
| } |
| else if (__way == ios_base::end) |
| __base = _M_buf.size(); |
| |
| if (__builtin_add_overflow(__base, __off, &__off)) |
| return __ret; |
| |
| if (__off < 0 || __off > _M_buf.size()) |
| return __ret; |
| |
| if (__which & ios_base::in) |
| this->setg(this->eback(), this->eback() + __off, this->egptr()); |
| |
| if (__which & ios_base::out) |
| { |
| this->setp(this->pbase(), this->epptr()); |
| this->pbump(__off); |
| } |
| |
| __ret = pos_type(__off); |
| |
| } |
| return __ret; |
| } |
| |
| pos_type |
| seekpos(pos_type __sp, |
| ios_base::openmode __which = ios_base::in | ios_base::out) override |
| { return seekoff(off_type(__sp), ios_base::beg, __which); } |
| |
| private: |
| |
| ios_base::openmode _M_mode; |
| std::span<_CharT> _M_buf; |
| }; |
| |
| template<typename _CharT, typename _Traits> |
| inline void |
| swap(basic_spanbuf<_CharT, _Traits>& __x, |
| basic_spanbuf<_CharT, _Traits>& __y) |
| { __x.swap(__y); } |
| |
| using spanbuf = basic_spanbuf<char>; |
| using wspanbuf = basic_spanbuf<wchar_t>; |
| |
| template<typename _CharT, typename _Traits> |
| class basic_ispanstream |
| : public basic_istream<_CharT, _Traits> |
| { |
| using __istream_type = 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.ctor], constructors |
| explicit |
| basic_ispanstream(std::span<_CharT> __s, |
| ios_base::openmode __which = ios_base::in) |
| : __istream_type(std::__addressof(_M_sb)), |
| _M_sb(__s, __which | ios_base::in) |
| { } |
| |
| basic_ispanstream(const basic_ispanstream&) = delete; |
| |
| basic_ispanstream(basic_ispanstream&& __rhs) |
| : __istream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb)) |
| { |
| __istream_type::set_rdbuf(std::addressof(_M_sb)); |
| } |
| |
| template<typename _Ros> |
| requires ranges::borrowed_range<_Ros> |
| && (!convertible_to<_Ros, std::span<_CharT>>) |
| && convertible_to<_Ros, std::span<const _CharT>> |
| explicit |
| basic_ispanstream(_Ros&& __s) |
| : __istream_type(std::__addressof(_M_sb)), |
| _M_sb(ios_base::in) |
| { |
| std::span<const _CharT> __sp(std::forward<_Ros>(__s)); |
| _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()}); |
| } |
| |
| // [ispanstream.assign], assignment and swap |
| basic_ispanstream& operator=(const basic_ispanstream&) = delete; |
| basic_ispanstream& operator=(basic_ispanstream&& __rhs) = default; |
| |
| void |
| swap(basic_ispanstream& __rhs) |
| { |
| __istream_type::swap(__rhs); |
| _M_sb.swap(__rhs._M_sb); |
| } |
| |
| // [ispanstream.members], member functions |
| basic_spanbuf<_CharT, _Traits>* |
| rdbuf() const noexcept |
| { |
| return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb)); |
| } |
| |
| std::span<const _CharT> |
| span() const noexcept |
| { return _M_sb.span(); } |
| |
| void |
| span(std::span<_CharT> __s) noexcept |
| { return _M_sb.span(__s); } |
| |
| template<typename _Ros> |
| requires ranges::borrowed_range<_Ros> |
| && (!convertible_to<_Ros, std::span<_CharT>>) |
| && convertible_to<_Ros, std::span<const _CharT>> |
| void |
| span(_Ros&& __s) noexcept |
| { |
| std::span<const _CharT> __sp(std::forward<_Ros>(__s)); |
| _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()}); |
| } |
| |
| private: |
| basic_spanbuf<_CharT, _Traits> _M_sb; |
| }; |
| |
| template<typename _CharT, typename _Traits> |
| inline void |
| swap(basic_ispanstream<_CharT, _Traits>& __x, |
| basic_ispanstream<_CharT, _Traits>& __y) |
| { __x.swap(__y); } |
| |
| using ispanstream = basic_ispanstream<char>; |
| using wispanstream = basic_ispanstream<wchar_t>; |
| |
| template<typename _CharT, typename _Traits> |
| class basic_ospanstream |
| : public basic_ostream<_CharT, _Traits> |
| { |
| using __ostream_type = 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.ctor], constructors |
| explicit |
| basic_ospanstream(std::span<_CharT> __s, |
| ios_base::openmode __which = ios_base::out) |
| : __ostream_type(std::__addressof(_M_sb)), |
| _M_sb(__s, __which | ios_base::in) |
| { } |
| |
| basic_ospanstream(const basic_ospanstream&) = delete; |
| |
| basic_ospanstream(basic_ospanstream&& __rhs) |
| : __ostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb)) |
| { |
| __ostream_type::set_rdbuf(std::addressof(_M_sb)); |
| } |
| |
| // [ospanstream.assign], assignment and swap |
| basic_ospanstream& operator=(const basic_ospanstream&) = delete; |
| basic_ospanstream& operator=(basic_ospanstream&& __rhs) = default; |
| |
| void |
| swap(basic_ospanstream& __rhs) |
| { |
| __ostream_type::swap(__rhs); |
| _M_sb.swap(__rhs._M_sb); |
| } |
| |
| // [ospanstream.members], member functions |
| basic_spanbuf<_CharT, _Traits>* |
| rdbuf() const noexcept |
| { |
| return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb)); |
| } |
| |
| std::span<_CharT> |
| span() const noexcept |
| { return _M_sb.span(); } |
| |
| void |
| span(std::span<_CharT> __s) noexcept |
| { return _M_sb.span(__s); } |
| |
| private: |
| basic_spanbuf<_CharT, _Traits> _M_sb; |
| }; |
| |
| template<typename _CharT, typename _Traits> |
| inline void |
| swap(basic_ospanstream<_CharT, _Traits>& __x, |
| basic_ospanstream<_CharT, _Traits>& __y) |
| { __x.swap(__y); } |
| |
| using ospanstream = basic_ospanstream<char>; |
| using wospanstream = basic_ospanstream<wchar_t>; |
| |
| template<typename _CharT, typename _Traits> |
| class basic_spanstream |
| : public basic_iostream<_CharT, _Traits> |
| { |
| using __iostream_type = 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.ctor], constructors |
| explicit |
| basic_spanstream(std::span<_CharT> __s, |
| ios_base::openmode __which = ios_base::out | ios_base::in) |
| : __iostream_type(std::__addressof(_M_sb)), |
| _M_sb(__s, __which) |
| { } |
| |
| basic_spanstream(const basic_spanstream&) = delete; |
| |
| basic_spanstream(basic_spanstream&& __rhs) |
| : __iostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb)) |
| { |
| __iostream_type::set_rdbuf(std::addressof(_M_sb)); |
| } |
| |
| // [spanstream.assign], assignment and swap |
| basic_spanstream& operator=(const basic_spanstream&) = delete; |
| basic_spanstream& operator=(basic_spanstream&& __rhs) = default; |
| |
| void |
| swap(basic_spanstream& __rhs) |
| { |
| __iostream_type::swap(__rhs); |
| _M_sb.swap(__rhs._M_sb); |
| } |
| |
| // [spanstream.members], members |
| basic_spanbuf<_CharT, _Traits>* |
| rdbuf() const noexcept |
| { |
| return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb)); |
| } |
| |
| std::span<_CharT> |
| span() const noexcept |
| { return _M_sb.span(); } |
| |
| void |
| span(std::span<_CharT> __s) noexcept |
| { return _M_sb.span(__s); } |
| |
| private: |
| basic_spanbuf<_CharT, _Traits> _M_sb; |
| }; |
| |
| template<typename _CharT, typename _Traits> |
| inline void |
| swap(basic_spanstream<_CharT, _Traits>& __x, |
| basic_spanstream<_CharT, _Traits>& __y) |
| { __x.swap(__y); } |
| |
| using spanstream = basic_spanstream<char>; |
| using wspanstream = basic_spanstream<wchar_t>; |
| |
| _GLIBCXX_END_NAMESPACE_VERSION |
| } // namespace std |
| #endif // __cpp_lib_span |
| #endif // C++23 |
| #endif // _GLIBCXX_SPANSTREAM |