// 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 // . /** @file spanstream * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_SPANSTREAM #define _GLIBCXX_SPANSTREAM 1 #pragma GCC system_header #include // iostreams #if __cplusplus > 202002L #include #include #include #include #include #if __cpp_lib_span namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION #define __cpp_lib_spanstream 202106L template 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 inline void swap(basic_spanbuf<_CharT, _Traits>& __x, basic_spanbuf<_CharT, _Traits>& __y) { __x.swap(__y); } using spanbuf = basic_spanbuf; using wspanbuf = basic_spanbuf; template 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 requires ranges::borrowed_range<_Ros> && (!convertible_to<_Ros, std::span<_CharT>>) && convertible_to<_Ros, std::span> explicit basic_ispanstream(_Ros&& __s) : __istream_type(std::__addressof(_M_sb)), _M_sb(ios_base::in) { std::span __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*>(std::__addressof(_M_sb)); } std::span span() const noexcept { return _M_sb.span(); } void span(std::span<_CharT> __s) noexcept { return _M_sb.span(__s); } template requires ranges::borrowed_range<_Ros> && (!convertible_to<_Ros, std::span<_CharT>>) && convertible_to<_Ros, std::span> void span(_Ros&& __s) noexcept { std::span __sp(std::forward<_Ros>(__s)); _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()}); } private: basic_spanbuf<_CharT, _Traits> _M_sb; }; template inline void swap(basic_ispanstream<_CharT, _Traits>& __x, basic_ispanstream<_CharT, _Traits>& __y) { __x.swap(__y); } using ispanstream = basic_ispanstream; using wispanstream = basic_ispanstream; template 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*>(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 inline void swap(basic_ospanstream<_CharT, _Traits>& __x, basic_ospanstream<_CharT, _Traits>& __y) { __x.swap(__y); } using ospanstream = basic_ospanstream; using wospanstream = basic_ospanstream; template 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*>(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 inline void swap(basic_spanstream<_CharT, _Traits>& __x, basic_spanstream<_CharT, _Traits>& __y) { __x.swap(__y); } using spanstream = basic_spanstream; using wspanstream = basic_spanstream; _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __cpp_lib_span #endif // C++23 #endif // _GLIBCXX_SPANSTREAM