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