1b1e83836Smrg// Streams based on std::span -*- C++ -*- 2b1e83836Smrg 3b1e83836Smrg// Copyright The GNU Toolchain Authors. 4b1e83836Smrg// 5b1e83836Smrg// This file is part of the GNU ISO C++ Library. This library is free 6b1e83836Smrg// software; you can redistribute it and/or modify it under the 7b1e83836Smrg// terms of the GNU General Public License as published by the 8b1e83836Smrg// Free Software Foundation; either version 3, or (at your option) 9b1e83836Smrg// any later version. 10b1e83836Smrg 11b1e83836Smrg// This library is distributed in the hope that it will be useful, 12b1e83836Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 13b1e83836Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14b1e83836Smrg// GNU General Public License for more details. 15b1e83836Smrg 16b1e83836Smrg// Under Section 7 of GPL version 3, you are granted additional 17b1e83836Smrg// permissions described in the GCC Runtime Library Exception, version 18b1e83836Smrg// 3.1, as published by the Free Software Foundation. 19b1e83836Smrg 20b1e83836Smrg// You should have received a copy of the GNU General Public License and 21b1e83836Smrg// a copy of the GCC Runtime Library Exception along with this program; 22b1e83836Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23b1e83836Smrg// <http://www.gnu.org/licenses/>. 24b1e83836Smrg 25b1e83836Smrg/** @file spanstream 26b1e83836Smrg * This is a Standard C++ Library header. 27b1e83836Smrg */ 28b1e83836Smrg 29b1e83836Smrg#ifndef _GLIBCXX_SPANSTREAM 30b1e83836Smrg#define _GLIBCXX_SPANSTREAM 1 31b1e83836Smrg 32b1e83836Smrg#pragma GCC system_header 33b1e83836Smrg 34b1e83836Smrg#if __cplusplus > 202002L 35b1e83836Smrg#include <span> 36b1e83836Smrg#include <streambuf> 37b1e83836Smrg#include <istream> 38b1e83836Smrg#include <ostream> 39b1e83836Smrg#include <bits/ranges_base.h> 40b1e83836Smrg 41b1e83836Smrg#if __cpp_lib_span 42b1e83836Smrgnamespace std _GLIBCXX_VISIBILITY(default) 43b1e83836Smrg{ 44b1e83836Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 45b1e83836Smrg 46b1e83836Smrg#define __cpp_lib_spanstream 202106L 47b1e83836Smrg 48b1e83836Smrgtemplate<typename _CharT, typename _Traits> 49b1e83836Smrg class basic_spanbuf 50b1e83836Smrg : public basic_streambuf<_CharT, _Traits> 51b1e83836Smrg { 52b1e83836Smrg using __streambuf_type = basic_streambuf<_CharT, _Traits>; 53b1e83836Smrg 54b1e83836Smrg public: 55b1e83836Smrg using char_type = _CharT; 56b1e83836Smrg using int_type = typename _Traits::int_type; 57b1e83836Smrg using pos_type = typename _Traits::pos_type; 58b1e83836Smrg using off_type = typename _Traits::off_type; 59b1e83836Smrg using traits_type = _Traits; 60b1e83836Smrg 61b1e83836Smrg // [spanbuf.ctor], constructors 62b1e83836Smrg basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out) 63b1e83836Smrg { } 64b1e83836Smrg 65b1e83836Smrg explicit 66b1e83836Smrg basic_spanbuf(ios_base::openmode __which) 67b1e83836Smrg : __streambuf_type(), _M_mode(__which) 68b1e83836Smrg { } 69b1e83836Smrg 70b1e83836Smrg explicit 71b1e83836Smrg basic_spanbuf(std::span<_CharT> __s, 72b1e83836Smrg ios_base::openmode __which = ios_base::in | ios_base::out) 73b1e83836Smrg : __streambuf_type(), _M_mode(__which) 74b1e83836Smrg { span(__s); } 75b1e83836Smrg 76b1e83836Smrg basic_spanbuf(const basic_spanbuf&) = delete; 77b1e83836Smrg 78b1e83836Smrg /** Move constructor. 79b1e83836Smrg * 80b1e83836Smrg * Transfers the buffer and pointers into the get and put areas from 81b1e83836Smrg * `__rhs` to `*this`. 82b1e83836Smrg * 83b1e83836Smrg * In this implementation `rhs` is left unchanged, 84b1e83836Smrg * but that is not guaranteed by the standard. 85b1e83836Smrg */ 86b1e83836Smrg basic_spanbuf(basic_spanbuf&& __rhs) 87b1e83836Smrg : __streambuf_type(__rhs), _M_mode(__rhs._M_mode), _M_buf(__rhs._M_buf) 88b1e83836Smrg { } 89b1e83836Smrg 90b1e83836Smrg // [spanbuf.assign], assignment and swap 91b1e83836Smrg basic_spanbuf& operator=(const basic_spanbuf&) = delete; 92b1e83836Smrg 93b1e83836Smrg basic_spanbuf& 94b1e83836Smrg operator=(basic_spanbuf&& __rhs) 95b1e83836Smrg { 96b1e83836Smrg basic_spanbuf(std::move(__rhs)).swap(*this); 97b1e83836Smrg return *this; 98b1e83836Smrg } 99b1e83836Smrg 100b1e83836Smrg void 101b1e83836Smrg swap(basic_spanbuf& __rhs) 102b1e83836Smrg { 103b1e83836Smrg __streambuf_type::swap(__rhs); 104b1e83836Smrg std::swap(_M_mode, __rhs._M_mode); 105b1e83836Smrg std::swap(_M_buf, __rhs._M_buf); 106b1e83836Smrg } 107b1e83836Smrg 108b1e83836Smrg // [spanbuf.members], member functions 109b1e83836Smrg std::span<_CharT> 110b1e83836Smrg span() const noexcept 111b1e83836Smrg { 112b1e83836Smrg if (_M_mode & ios_base::out) 113b1e83836Smrg return {this->pbase(), this->pptr()}; 114b1e83836Smrg else 115b1e83836Smrg return _M_buf; 116b1e83836Smrg } 117b1e83836Smrg 118b1e83836Smrg void 119b1e83836Smrg span(std::span<_CharT> __s) noexcept 120b1e83836Smrg { 121b1e83836Smrg _M_buf = __s; 122b1e83836Smrg if (_M_mode & ios_base::out) 123b1e83836Smrg { 124b1e83836Smrg this->setp(__s.data(), __s.data() + __s.size()); 125b1e83836Smrg if (_M_mode & ios_base::ate) 126b1e83836Smrg this->pbump(__s.size()); 127b1e83836Smrg } 128b1e83836Smrg if (_M_mode & ios_base::in) 129b1e83836Smrg this->setg(__s.data(), __s.data(), __s.data() + __s.size()); 130b1e83836Smrg } 131b1e83836Smrg 132b1e83836Smrg protected: 133b1e83836Smrg // [spanbuf.virtuals], overridden virtual functions 134b1e83836Smrg basic_streambuf<_CharT, _Traits>* 135b1e83836Smrg setbuf(_CharT* __s, streamsize __n) override 136b1e83836Smrg { 137*0a307195Smrg __glibcxx_assert(__n >= 0); 138*0a307195Smrg this->span(std::span<_CharT>(__s, __n)); 139b1e83836Smrg return this; 140b1e83836Smrg } 141b1e83836Smrg 142b1e83836Smrg pos_type 143b1e83836Smrg seekoff(off_type __off, ios_base::seekdir __way, 144b1e83836Smrg ios_base::openmode __which = ios_base::in | ios_base::out) override 145b1e83836Smrg { 146b1e83836Smrg pos_type __ret = pos_type(off_type(-1)); 147b1e83836Smrg 148b1e83836Smrg if (__way == ios_base::beg) 149b1e83836Smrg { 150b1e83836Smrg if (0 <= __off && __off <= _M_buf.size()) 151b1e83836Smrg { 152b1e83836Smrg if (__which & ios_base::in) 153b1e83836Smrg this->setg(this->eback(), this->eback() + __off, this->egptr()); 154b1e83836Smrg 155b1e83836Smrg if (__which & ios_base::out) 156b1e83836Smrg { 157b1e83836Smrg this->setp(this->pbase(), this->epptr()); 158b1e83836Smrg this->pbump(__off); 159b1e83836Smrg } 160b1e83836Smrg 161b1e83836Smrg __ret = pos_type(__off); 162b1e83836Smrg } 163b1e83836Smrg } 164b1e83836Smrg else 165b1e83836Smrg { 166b1e83836Smrg off_type __base; 167b1e83836Smrg __which &= (ios_base::in|ios_base::out); 168b1e83836Smrg 169b1e83836Smrg if (__which == ios_base::out) 170b1e83836Smrg __base = this->pptr() - this->pbase(); 171b1e83836Smrg else if (__way == ios_base::cur) 172b1e83836Smrg { 173b1e83836Smrg if (__which == ios_base::in) 174b1e83836Smrg __base = this->gptr() - this->eback(); 175b1e83836Smrg else 176b1e83836Smrg return __ret; 177b1e83836Smrg } 178b1e83836Smrg else if (__way == ios_base::end) 179b1e83836Smrg __base = _M_buf.size(); 180b1e83836Smrg 181b1e83836Smrg if (__builtin_add_overflow(__base, __off, &__off)) 182b1e83836Smrg return __ret; 183b1e83836Smrg 184b1e83836Smrg if (__off < 0 || __off > _M_buf.size()) 185b1e83836Smrg return __ret; 186b1e83836Smrg 187b1e83836Smrg if (__which & ios_base::in) 188b1e83836Smrg this->setg(this->eback(), this->eback() + __off, this->egptr()); 189b1e83836Smrg 190b1e83836Smrg if (__which & ios_base::out) 191b1e83836Smrg { 192b1e83836Smrg this->setp(this->pbase(), this->epptr()); 193b1e83836Smrg this->pbump(__off); 194b1e83836Smrg } 195b1e83836Smrg 196b1e83836Smrg __ret = pos_type(__off); 197b1e83836Smrg 198b1e83836Smrg } 199b1e83836Smrg return __ret; 200b1e83836Smrg } 201b1e83836Smrg 202b1e83836Smrg pos_type 203b1e83836Smrg seekpos(pos_type __sp, 204b1e83836Smrg ios_base::openmode __which = ios_base::in | ios_base::out) override 205b1e83836Smrg { return seekoff(off_type(__sp), ios_base::beg, __which); } 206b1e83836Smrg 207b1e83836Smrg private: 208b1e83836Smrg 209b1e83836Smrg ios_base::openmode _M_mode; 210b1e83836Smrg std::span<_CharT> _M_buf; 211b1e83836Smrg }; 212b1e83836Smrg 213b1e83836Smrgtemplate<typename _CharT, typename _Traits> 214b1e83836Smrg inline void 215b1e83836Smrg swap(basic_spanbuf<_CharT, _Traits>& __x, 216b1e83836Smrg basic_spanbuf<_CharT, _Traits>& __y) 217b1e83836Smrg { __x.swap(__y); } 218b1e83836Smrg 219b1e83836Smrgusing spanbuf = basic_spanbuf<char>; 220b1e83836Smrgusing wspanbuf = basic_spanbuf<wchar_t>; 221b1e83836Smrg 222b1e83836Smrgtemplate<typename _CharT, typename _Traits> 223b1e83836Smrg class basic_ispanstream 224b1e83836Smrg : public basic_istream<_CharT, _Traits> 225b1e83836Smrg { 226b1e83836Smrg using __istream_type = basic_istream<_CharT, _Traits>; 227b1e83836Smrg 228b1e83836Smrg public: 229b1e83836Smrg using char_type = _CharT; 230b1e83836Smrg using int_type = typename _Traits::int_type; 231b1e83836Smrg using pos_type = typename _Traits::pos_type; 232b1e83836Smrg using off_type = typename _Traits::off_type; 233b1e83836Smrg using traits_type = _Traits; 234b1e83836Smrg 235b1e83836Smrg // [ispanstream.ctor], constructors 236b1e83836Smrg explicit 237b1e83836Smrg basic_ispanstream(std::span<_CharT> __s, 238b1e83836Smrg ios_base::openmode __which = ios_base::in) 239b1e83836Smrg : __istream_type(std::__addressof(_M_sb)), 240b1e83836Smrg _M_sb(__s, __which | ios_base::in) 241b1e83836Smrg { } 242b1e83836Smrg 243b1e83836Smrg basic_ispanstream(const basic_ispanstream&) = delete; 244b1e83836Smrg 245b1e83836Smrg basic_ispanstream(basic_ispanstream&& __rhs) 246b1e83836Smrg : __istream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb)) 247b1e83836Smrg { 248b1e83836Smrg __istream_type::set_rdbuf(std::addressof(_M_sb)); 249b1e83836Smrg } 250b1e83836Smrg 251b1e83836Smrg template<typename _Ros> 252b1e83836Smrg requires ranges::borrowed_range<_Ros> 253b1e83836Smrg && (!convertible_to<_Ros, std::span<_CharT>>) 254b1e83836Smrg && convertible_to<_Ros, std::span<const _CharT>> 255b1e83836Smrg explicit 256b1e83836Smrg basic_ispanstream(_Ros&& __s) 257b1e83836Smrg : __istream_type(std::__addressof(_M_sb)), 258b1e83836Smrg _M_sb(ios_base::in) 259b1e83836Smrg { 260b1e83836Smrg std::span<const _CharT> __sp(std::forward<_Ros>(__s)); 261b1e83836Smrg _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()}); 262b1e83836Smrg } 263b1e83836Smrg 264b1e83836Smrg // [ispanstream.assign], assignment and swap 265b1e83836Smrg basic_ispanstream& operator=(const basic_ispanstream&) = delete; 266b1e83836Smrg basic_ispanstream& operator=(basic_ispanstream&& __rhs) = default; 267b1e83836Smrg 268b1e83836Smrg void 269b1e83836Smrg swap(basic_ispanstream& __rhs) 270b1e83836Smrg { 271b1e83836Smrg __istream_type::swap(__rhs); 272b1e83836Smrg _M_sb.swap(__rhs._M_sb); 273b1e83836Smrg } 274b1e83836Smrg 275b1e83836Smrg // [ispanstream.members], member functions 276b1e83836Smrg basic_spanbuf<_CharT, _Traits>* 277b1e83836Smrg rdbuf() const noexcept 278b1e83836Smrg { 279b1e83836Smrg return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb)); 280b1e83836Smrg } 281b1e83836Smrg 282b1e83836Smrg std::span<const _CharT> 283b1e83836Smrg span() const noexcept 284b1e83836Smrg { return _M_sb.span(); } 285b1e83836Smrg 286b1e83836Smrg void 287b1e83836Smrg span(std::span<_CharT> __s) noexcept 288b1e83836Smrg { return _M_sb.span(__s); } 289b1e83836Smrg 290b1e83836Smrg template<typename _Ros> 291b1e83836Smrg requires ranges::borrowed_range<_Ros> 292b1e83836Smrg && (!convertible_to<_Ros, std::span<_CharT>>) 293b1e83836Smrg && convertible_to<_Ros, std::span<const _CharT>> 294b1e83836Smrg void 295b1e83836Smrg span(_Ros&& __s) noexcept 296b1e83836Smrg { 297b1e83836Smrg std::span<const _CharT> __sp(std::forward<_Ros>(__s)); 298b1e83836Smrg _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()}); 299b1e83836Smrg } 300b1e83836Smrg 301b1e83836Smrg private: 302b1e83836Smrg basic_spanbuf<_CharT, _Traits> _M_sb; 303b1e83836Smrg }; 304b1e83836Smrg 305b1e83836Smrgtemplate<typename _CharT, typename _Traits> 306b1e83836Smrg inline void 307b1e83836Smrg swap(basic_ispanstream<_CharT, _Traits>& __x, 308b1e83836Smrg basic_ispanstream<_CharT, _Traits>& __y) 309b1e83836Smrg { __x.swap(__y); } 310b1e83836Smrg 311b1e83836Smrgusing ispanstream = basic_ispanstream<char>; 312b1e83836Smrgusing wispanstream = basic_ispanstream<wchar_t>; 313b1e83836Smrg 314b1e83836Smrgtemplate<typename _CharT, typename _Traits> 315b1e83836Smrg class basic_ospanstream 316b1e83836Smrg : public basic_ostream<_CharT, _Traits> 317b1e83836Smrg { 318b1e83836Smrg using __ostream_type = basic_ostream<_CharT, _Traits>; 319b1e83836Smrg 320b1e83836Smrg public: 321b1e83836Smrg using char_type = _CharT; 322b1e83836Smrg using int_type = typename _Traits::int_type; 323b1e83836Smrg using pos_type = typename _Traits::pos_type; 324b1e83836Smrg using off_type = typename _Traits::off_type; 325b1e83836Smrg using traits_type = _Traits; 326b1e83836Smrg 327b1e83836Smrg // [ospanstream.ctor], constructors 328b1e83836Smrg explicit 329b1e83836Smrg basic_ospanstream(std::span<_CharT> __s, 330b1e83836Smrg ios_base::openmode __which = ios_base::out) 331b1e83836Smrg : __ostream_type(std::__addressof(_M_sb)), 332b1e83836Smrg _M_sb(__s, __which | ios_base::in) 333b1e83836Smrg { } 334b1e83836Smrg 335b1e83836Smrg basic_ospanstream(const basic_ospanstream&) = delete; 336b1e83836Smrg 337b1e83836Smrg basic_ospanstream(basic_ospanstream&& __rhs) 338b1e83836Smrg : __ostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb)) 339b1e83836Smrg { 340b1e83836Smrg __ostream_type::set_rdbuf(std::addressof(_M_sb)); 341b1e83836Smrg } 342b1e83836Smrg 343b1e83836Smrg // [ospanstream.assign], assignment and swap 344b1e83836Smrg basic_ospanstream& operator=(const basic_ospanstream&) = delete; 345b1e83836Smrg basic_ospanstream& operator=(basic_ospanstream&& __rhs) = default; 346b1e83836Smrg 347b1e83836Smrg void 348b1e83836Smrg swap(basic_ospanstream& __rhs) 349b1e83836Smrg { 350b1e83836Smrg __ostream_type::swap(__rhs); 351b1e83836Smrg _M_sb.swap(__rhs._M_sb); 352b1e83836Smrg } 353b1e83836Smrg 354b1e83836Smrg // [ospanstream.members], member functions 355b1e83836Smrg basic_spanbuf<_CharT, _Traits>* 356b1e83836Smrg rdbuf() const noexcept 357b1e83836Smrg { 358b1e83836Smrg return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb)); 359b1e83836Smrg } 360b1e83836Smrg 361b1e83836Smrg std::span<_CharT> 362b1e83836Smrg span() const noexcept 363b1e83836Smrg { return _M_sb.span(); } 364b1e83836Smrg 365b1e83836Smrg void 366b1e83836Smrg span(std::span<_CharT> __s) noexcept 367b1e83836Smrg { return _M_sb.span(__s); } 368b1e83836Smrg 369b1e83836Smrg private: 370b1e83836Smrg basic_spanbuf<_CharT, _Traits> _M_sb; 371b1e83836Smrg }; 372b1e83836Smrg 373b1e83836Smrgtemplate<typename _CharT, typename _Traits> 374b1e83836Smrg inline void 375b1e83836Smrg swap(basic_ospanstream<_CharT, _Traits>& __x, 376b1e83836Smrg basic_ospanstream<_CharT, _Traits>& __y) 377b1e83836Smrg { __x.swap(__y); } 378b1e83836Smrg 379b1e83836Smrgusing ospanstream = basic_ospanstream<char>; 380b1e83836Smrgusing wospanstream = basic_ospanstream<wchar_t>; 381b1e83836Smrg 382b1e83836Smrgtemplate<typename _CharT, typename _Traits> 383b1e83836Smrg class basic_spanstream 384b1e83836Smrg : public basic_iostream<_CharT, _Traits> 385b1e83836Smrg { 386b1e83836Smrg using __iostream_type = basic_iostream<_CharT, _Traits>; 387b1e83836Smrg 388b1e83836Smrg public: 389b1e83836Smrg using char_type = _CharT; 390b1e83836Smrg using int_type = typename _Traits::int_type; 391b1e83836Smrg using pos_type = typename _Traits::pos_type; 392b1e83836Smrg using off_type = typename _Traits::off_type; 393b1e83836Smrg using traits_type = _Traits; 394b1e83836Smrg 395b1e83836Smrg // [spanstream.ctor], constructors 396b1e83836Smrg explicit 397b1e83836Smrg basic_spanstream(std::span<_CharT> __s, 398b1e83836Smrg ios_base::openmode __which = ios_base::out | ios_base::in) 399b1e83836Smrg : __iostream_type(std::__addressof(_M_sb)), 400b1e83836Smrg _M_sb(__s, __which) 401b1e83836Smrg { } 402b1e83836Smrg 403b1e83836Smrg basic_spanstream(const basic_spanstream&) = delete; 404b1e83836Smrg 405b1e83836Smrg basic_spanstream(basic_spanstream&& __rhs) 406b1e83836Smrg : __iostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb)) 407b1e83836Smrg { 408b1e83836Smrg __iostream_type::set_rdbuf(std::addressof(_M_sb)); 409b1e83836Smrg } 410b1e83836Smrg 411b1e83836Smrg // [spanstream.assign], assignment and swap 412b1e83836Smrg basic_spanstream& operator=(const basic_spanstream&) = delete; 413b1e83836Smrg basic_spanstream& operator=(basic_spanstream&& __rhs) = default; 414b1e83836Smrg 415b1e83836Smrg void 416b1e83836Smrg swap(basic_spanstream& __rhs) 417b1e83836Smrg { 418b1e83836Smrg __iostream_type::swap(__rhs); 419b1e83836Smrg _M_sb.swap(__rhs._M_sb); 420b1e83836Smrg } 421b1e83836Smrg 422b1e83836Smrg // [spanstream.members], members 423b1e83836Smrg basic_spanbuf<_CharT, _Traits>* 424b1e83836Smrg rdbuf() const noexcept 425b1e83836Smrg { 426b1e83836Smrg return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb)); 427b1e83836Smrg } 428b1e83836Smrg 429b1e83836Smrg std::span<_CharT> 430b1e83836Smrg span() const noexcept 431b1e83836Smrg { return _M_sb.span(); } 432b1e83836Smrg 433b1e83836Smrg void 434b1e83836Smrg span(std::span<_CharT> __s) noexcept 435b1e83836Smrg { return _M_sb.span(__s); } 436b1e83836Smrg 437b1e83836Smrg private: 438b1e83836Smrg basic_spanbuf<_CharT, _Traits> _M_sb; 439b1e83836Smrg }; 440b1e83836Smrg 441b1e83836Smrgtemplate<typename _CharT, typename _Traits> 442b1e83836Smrg inline void 443b1e83836Smrg swap(basic_spanstream<_CharT, _Traits>& __x, 444b1e83836Smrg basic_spanstream<_CharT, _Traits>& __y) 445b1e83836Smrg { __x.swap(__y); } 446b1e83836Smrg 447b1e83836Smrgusing spanstream = basic_spanstream<char>; 448b1e83836Smrgusing wspanstream = basic_spanstream<wchar_t>; 449b1e83836Smrg 450b1e83836Smrg_GLIBCXX_END_NAMESPACE_VERSION 451b1e83836Smrg} // namespace std 452b1e83836Smrg#endif // __cpp_lib_span 453b1e83836Smrg#endif // C++23 454b1e83836Smrg#endif // _GLIBCXX_SPANSTREAM 455