1 // Streams based on std::span -*- C++ -*-
3 // Copyright The GNU Toolchain Authors.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
26 * This is a Standard C++ Library header.
29 #ifndef _GLIBCXX_SPANSTREAM
30 #define _GLIBCXX_SPANSTREAM 1
32 #pragma GCC system_header
34 #include <bits/requires_hosted.h> // iostreams
36 #if __cplusplus > 202002L
41 #include <bits/ranges_base.h>
44 namespace std _GLIBCXX_VISIBILITY(default)
46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
48 #define __cpp_lib_spanstream 202106L
50 template<typename _CharT, typename _Traits>
52 : public basic_streambuf<_CharT, _Traits>
54 using __streambuf_type = basic_streambuf<_CharT, _Traits>;
57 using char_type = _CharT;
58 using int_type = typename _Traits::int_type;
59 using pos_type = typename _Traits::pos_type;
60 using off_type = typename _Traits::off_type;
61 using traits_type = _Traits;
63 // [spanbuf.ctor], constructors
64 basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out)
68 basic_spanbuf(ios_base::openmode __which)
69 : __streambuf_type(), _M_mode(__which)
73 basic_spanbuf(std::span<_CharT> __s,
74 ios_base::openmode __which = ios_base::in | ios_base::out)
75 : __streambuf_type(), _M_mode(__which)
78 basic_spanbuf(const basic_spanbuf&) = delete;
82 * Transfers the buffer and pointers into the get and put areas from
85 * In this implementation `rhs` is left unchanged,
86 * but that is not guaranteed by the standard.
88 basic_spanbuf(basic_spanbuf&& __rhs)
89 : __streambuf_type(__rhs), _M_mode(__rhs._M_mode), _M_buf(__rhs._M_buf)
92 // [spanbuf.assign], assignment and swap
93 basic_spanbuf& operator=(const basic_spanbuf&) = delete;
96 operator=(basic_spanbuf&& __rhs)
98 basic_spanbuf(std::move(__rhs)).swap(*this);
103 swap(basic_spanbuf& __rhs)
105 __streambuf_type::swap(__rhs);
106 std::swap(_M_mode, __rhs._M_mode);
107 std::swap(_M_buf, __rhs._M_buf);
110 // [spanbuf.members], member functions
112 span() const noexcept
114 if (_M_mode & ios_base::out)
115 return {this->pbase(), this->pptr()};
121 span(std::span<_CharT> __s) noexcept
124 if (_M_mode & ios_base::out)
126 this->setp(__s.data(), __s.data() + __s.size());
127 if (_M_mode & ios_base::ate)
128 this->pbump(__s.size());
130 if (_M_mode & ios_base::in)
131 this->setg(__s.data(), __s.data(), __s.data() + __s.size());
135 // [spanbuf.virtuals], overridden virtual functions
136 basic_streambuf<_CharT, _Traits>*
137 setbuf(_CharT* __s, streamsize __n) override
139 __glibcxx_assert(__n >= 0);
140 this->span(std::span<_CharT>(__s, __n));
145 seekoff(off_type __off, ios_base::seekdir __way,
146 ios_base::openmode __which = ios_base::in | ios_base::out) override
148 pos_type __ret = pos_type(off_type(-1));
150 if (__way == ios_base::beg)
152 if (0 <= __off && __off <= _M_buf.size())
154 if (__which & ios_base::in)
155 this->setg(this->eback(), this->eback() + __off, this->egptr());
157 if (__which & ios_base::out)
159 this->setp(this->pbase(), this->epptr());
163 __ret = pos_type(__off);
169 __which &= (ios_base::in|ios_base::out);
171 if (__which == ios_base::out)
172 __base = this->pptr() - this->pbase();
173 else if (__way == ios_base::cur)
175 if (__which == ios_base::in)
176 __base = this->gptr() - this->eback();
180 else if (__way == ios_base::end)
181 __base = _M_buf.size();
183 if (__builtin_add_overflow(__base, __off, &__off))
186 if (__off < 0 || __off > _M_buf.size())
189 if (__which & ios_base::in)
190 this->setg(this->eback(), this->eback() + __off, this->egptr());
192 if (__which & ios_base::out)
194 this->setp(this->pbase(), this->epptr());
198 __ret = pos_type(__off);
205 seekpos(pos_type __sp,
206 ios_base::openmode __which = ios_base::in | ios_base::out) override
207 { return seekoff(off_type(__sp), ios_base::beg, __which); }
211 ios_base::openmode _M_mode;
212 std::span<_CharT> _M_buf;
215 template<typename _CharT, typename _Traits>
217 swap(basic_spanbuf<_CharT, _Traits>& __x,
218 basic_spanbuf<_CharT, _Traits>& __y)
221 using spanbuf = basic_spanbuf<char>;
222 using wspanbuf = basic_spanbuf<wchar_t>;
224 template<typename _CharT, typename _Traits>
225 class basic_ispanstream
226 : public basic_istream<_CharT, _Traits>
228 using __istream_type = basic_istream<_CharT, _Traits>;
231 using char_type = _CharT;
232 using int_type = typename _Traits::int_type;
233 using pos_type = typename _Traits::pos_type;
234 using off_type = typename _Traits::off_type;
235 using traits_type = _Traits;
237 // [ispanstream.ctor], constructors
239 basic_ispanstream(std::span<_CharT> __s,
240 ios_base::openmode __which = ios_base::in)
241 : __istream_type(std::__addressof(_M_sb)),
242 _M_sb(__s, __which | ios_base::in)
245 basic_ispanstream(const basic_ispanstream&) = delete;
247 basic_ispanstream(basic_ispanstream&& __rhs)
248 : __istream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
250 __istream_type::set_rdbuf(std::addressof(_M_sb));
253 template<typename _Ros>
254 requires ranges::borrowed_range<_Ros>
255 && (!convertible_to<_Ros, std::span<_CharT>>)
256 && convertible_to<_Ros, std::span<const _CharT>>
258 basic_ispanstream(_Ros&& __s)
259 : __istream_type(std::__addressof(_M_sb)),
262 std::span<const _CharT> __sp(std::forward<_Ros>(__s));
263 _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
266 // [ispanstream.assign], assignment and swap
267 basic_ispanstream& operator=(const basic_ispanstream&) = delete;
268 basic_ispanstream& operator=(basic_ispanstream&& __rhs) = default;
271 swap(basic_ispanstream& __rhs)
273 __istream_type::swap(__rhs);
274 _M_sb.swap(__rhs._M_sb);
277 // [ispanstream.members], member functions
278 basic_spanbuf<_CharT, _Traits>*
279 rdbuf() const noexcept
281 return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
284 std::span<const _CharT>
285 span() const noexcept
286 { return _M_sb.span(); }
289 span(std::span<_CharT> __s) noexcept
290 { return _M_sb.span(__s); }
292 template<typename _Ros>
293 requires ranges::borrowed_range<_Ros>
294 && (!convertible_to<_Ros, std::span<_CharT>>)
295 && convertible_to<_Ros, std::span<const _CharT>>
297 span(_Ros&& __s) noexcept
299 std::span<const _CharT> __sp(std::forward<_Ros>(__s));
300 _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
304 basic_spanbuf<_CharT, _Traits> _M_sb;
307 template<typename _CharT, typename _Traits>
309 swap(basic_ispanstream<_CharT, _Traits>& __x,
310 basic_ispanstream<_CharT, _Traits>& __y)
313 using ispanstream = basic_ispanstream<char>;
314 using wispanstream = basic_ispanstream<wchar_t>;
316 template<typename _CharT, typename _Traits>
317 class basic_ospanstream
318 : public basic_ostream<_CharT, _Traits>
320 using __ostream_type = basic_ostream<_CharT, _Traits>;
323 using char_type = _CharT;
324 using int_type = typename _Traits::int_type;
325 using pos_type = typename _Traits::pos_type;
326 using off_type = typename _Traits::off_type;
327 using traits_type = _Traits;
329 // [ospanstream.ctor], constructors
331 basic_ospanstream(std::span<_CharT> __s,
332 ios_base::openmode __which = ios_base::out)
333 : __ostream_type(std::__addressof(_M_sb)),
334 _M_sb(__s, __which | ios_base::in)
337 basic_ospanstream(const basic_ospanstream&) = delete;
339 basic_ospanstream(basic_ospanstream&& __rhs)
340 : __ostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
342 __ostream_type::set_rdbuf(std::addressof(_M_sb));
345 // [ospanstream.assign], assignment and swap
346 basic_ospanstream& operator=(const basic_ospanstream&) = delete;
347 basic_ospanstream& operator=(basic_ospanstream&& __rhs) = default;
350 swap(basic_ospanstream& __rhs)
352 __ostream_type::swap(__rhs);
353 _M_sb.swap(__rhs._M_sb);
356 // [ospanstream.members], member functions
357 basic_spanbuf<_CharT, _Traits>*
358 rdbuf() const noexcept
360 return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
364 span() const noexcept
365 { return _M_sb.span(); }
368 span(std::span<_CharT> __s) noexcept
369 { return _M_sb.span(__s); }
372 basic_spanbuf<_CharT, _Traits> _M_sb;
375 template<typename _CharT, typename _Traits>
377 swap(basic_ospanstream<_CharT, _Traits>& __x,
378 basic_ospanstream<_CharT, _Traits>& __y)
381 using ospanstream = basic_ospanstream<char>;
382 using wospanstream = basic_ospanstream<wchar_t>;
384 template<typename _CharT, typename _Traits>
385 class basic_spanstream
386 : public basic_iostream<_CharT, _Traits>
388 using __iostream_type = basic_iostream<_CharT, _Traits>;
391 using char_type = _CharT;
392 using int_type = typename _Traits::int_type;
393 using pos_type = typename _Traits::pos_type;
394 using off_type = typename _Traits::off_type;
395 using traits_type = _Traits;
397 // [spanstream.ctor], constructors
399 basic_spanstream(std::span<_CharT> __s,
400 ios_base::openmode __which = ios_base::out | ios_base::in)
401 : __iostream_type(std::__addressof(_M_sb)),
405 basic_spanstream(const basic_spanstream&) = delete;
407 basic_spanstream(basic_spanstream&& __rhs)
408 : __iostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
410 __iostream_type::set_rdbuf(std::addressof(_M_sb));
413 // [spanstream.assign], assignment and swap
414 basic_spanstream& operator=(const basic_spanstream&) = delete;
415 basic_spanstream& operator=(basic_spanstream&& __rhs) = default;
418 swap(basic_spanstream& __rhs)
420 __iostream_type::swap(__rhs);
421 _M_sb.swap(__rhs._M_sb);
424 // [spanstream.members], members
425 basic_spanbuf<_CharT, _Traits>*
426 rdbuf() const noexcept
428 return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
432 span() const noexcept
433 { return _M_sb.span(); }
436 span(std::span<_CharT> __s) noexcept
437 { return _M_sb.span(__s); }
440 basic_spanbuf<_CharT, _Traits> _M_sb;
443 template<typename _CharT, typename _Traits>
445 swap(basic_spanstream<_CharT, _Traits>& __x,
446 basic_spanstream<_CharT, _Traits>& __y)
449 using spanstream = basic_spanstream<char>;
450 using wspanstream = basic_spanstream<wchar_t>;
452 _GLIBCXX_END_NAMESPACE_VERSION
454 #endif // __cpp_lib_span
456 #endif // _GLIBCXX_SPANSTREAM