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 #if __cplusplus > 202002L
39 #include <bits/ranges_base.h>
42 namespace std _GLIBCXX_VISIBILITY(default)
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 #define __cpp_lib_spanstream 202106L
48 template<typename _CharT, typename _Traits = char_traits<_CharT>>
50 : public basic_streambuf<_CharT, _Traits>
52 using __streambuf_type = basic_streambuf<_CharT, _Traits>;
55 using char_type = _CharT;
56 using int_type = typename _Traits::int_type;
57 using pos_type = typename _Traits::pos_type;
58 using off_type = typename _Traits::off_type;
59 using traits_type = _Traits;
61 // [spanbuf.ctor], constructors
62 basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out)
66 basic_spanbuf(ios_base::openmode __which)
67 : __streambuf_type(), _M_mode(__which)
71 basic_spanbuf(std::span<_CharT> __s,
72 ios_base::openmode __which = ios_base::in | ios_base::out)
73 : __streambuf_type(), _M_mode(__which)
76 basic_spanbuf(const basic_spanbuf&) = delete;
78 /// Move constructor. In this implementation `rhs` is left unchanged.
79 basic_spanbuf(basic_spanbuf&& __rhs)
80 : __streambuf_type(__rhs), _M_mode(__rhs._M_mode)
81 { span(__rhs._M_buf); }
83 // [spanbuf.assign], assignment and swap
84 basic_spanbuf& operator=(const basic_spanbuf&) = delete;
87 operator=(basic_spanbuf&& __rhs)
89 basic_spanbuf(std::move(__rhs))->swap(*this);
94 swap(basic_spanbuf& __rhs)
96 __streambuf_type::swap(__rhs);
97 std::swap(_M_mode, __rhs._M_mode);
98 std::swap(_M_buf, __rhs._M_buf);
101 // [spanbuf.members], member functions
103 span() const noexcept
105 if (_M_mode & ios_base::out)
106 return {this->pbase(), this->pptr()};
112 span(std::span<_CharT> __s) noexcept
115 if (_M_mode & ios_base::out)
117 this->setp(__s.data(), __s.data() + __s.size());
118 if (_M_mode & ios_base::ate)
119 this->pbump(__s.size());
121 if (_M_mode & ios_base::in)
122 this->setg(__s.data(), __s.data(), __s.data() + __s.size());
126 // [spanbuf.virtuals], overridden virtual functions
127 basic_streambuf<_CharT, _Traits>*
128 setbuf(_CharT* __s, streamsize __n) override
135 seekoff(off_type __off, ios_base::seekdir __way,
136 ios_base::openmode __which = ios_base::in | ios_base::out) override
138 pos_type __ret = pos_type(off_type(-1));
140 if (__way == ios_base::beg)
142 if (0 <= __off && __off <= _M_buf.size())
144 if (__which & ios_base::in)
145 this->setg(this->eback(), this->eback() + __off, this->egptr());
147 if (__which & ios_base::out)
149 this->setp(this->pbase(), this->epptr());
153 __ret = pos_type(__off);
159 __which &= (ios_base::in|ios_base::out);
161 if (__which == ios_base::out)
162 __base = this->pptr() - this->pbase();
163 else if (__way == ios_base::cur)
165 if (__which == ios_base::in)
166 __base = this->gptr() - this->eback();
170 else if (__way == ios_base::end)
171 __base = _M_buf.size();
173 if (__builtin_add_overflow(__base, __off, &__off))
176 if (__off < 0 || __off > _M_buf.size())
179 if (__which & ios_base::in)
180 this->setg(this->eback(), this->eback() + __off, this->egptr());
182 if (__which & ios_base::out)
184 this->setp(this->pbase(), this->epptr());
188 __ret = pos_type(__off);
195 seekpos(pos_type __sp,
196 ios_base::openmode __which = ios_base::in | ios_base::out) override
197 { return seekoff(off_type(__sp), ios_base::beg, __which); }
201 ios_base::openmode _M_mode;
202 std::span<_CharT> _M_buf;
205 template<typename _CharT, typename _Traits>
207 swap(basic_spanbuf<_CharT, _Traits>& __x,
208 basic_spanbuf<_CharT, _Traits>& __y)
211 using spanbuf = basic_spanbuf<char>;
212 using wspanbuf = basic_spanbuf<wchar_t>;
214 template<typename _CharT, typename _Traits = char_traits<_CharT>>
215 class basic_ispanstream
216 : public basic_istream<_CharT, _Traits>
218 using __istream_type = basic_istream<_CharT, _Traits>;
221 using char_type = _CharT;
222 using int_type = typename _Traits::int_type;
223 using pos_type = typename _Traits::pos_type;
224 using off_type = typename _Traits::off_type;
225 using traits_type = _Traits;
227 // [ispanstream.ctor], constructors
229 basic_ispanstream(std::span<_CharT> __s,
230 ios_base::openmode __which = ios_base::in)
231 : __istream_type(std::__addressof(_M_sb)),
232 _M_sb(__s, __which | ios_base::in)
235 basic_ispanstream(const basic_ispanstream&) = delete;
237 basic_ispanstream(basic_ispanstream&& __rhs)
238 : __istream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
240 __istream_type::set_rdbuf(std::addressof(_M_sb));
243 template<typename _Ros>
244 requires ranges::borrowed_range<_Ros>
245 && (!convertible_to<_Ros, std::span<_CharT>>)
246 && convertible_to<_Ros, std::span<const _CharT>>
248 basic_ispanstream(_Ros&& __s)
249 : __istream_type(std::__addressof(_M_sb)),
252 std::span<const _CharT> __sp(std::forward<_Ros>(__s));
253 _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
256 // [ispanstream.assign], assignment and swap
257 basic_ispanstream& operator=(const basic_ispanstream&) = delete;
258 basic_ispanstream& operator=(basic_ispanstream&& __rhs) = default;
261 swap(basic_ispanstream& __rhs)
263 __istream_type::swap(__rhs);
264 _M_sb.swap(__rhs._M_sb);
267 // [ispanstream.members], member functions
268 basic_spanbuf<_CharT, _Traits>*
269 rdbuf() const noexcept
271 return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
274 std::span<const _CharT>
275 span() const noexcept
276 { return _M_sb.span(); }
279 span(std::span<_CharT> __s) noexcept
280 { return _M_sb.span(__s); }
282 template<typename _Ros>
283 requires ranges::borrowed_range<_Ros>
284 && (!convertible_to<_Ros, std::span<_CharT>>)
285 && convertible_to<_Ros, std::span<const _CharT>>
287 span(_Ros&& __s) noexcept
289 std::span<const _CharT> __sp(std::forward<_Ros>(__s));
290 _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
294 basic_spanbuf<_CharT, _Traits> _M_sb;
297 template<typename _CharT, typename _Traits>
299 swap(basic_ispanstream<_CharT, _Traits>& __x,
300 basic_ispanstream<_CharT, _Traits>& __y)
303 using ispanstream = basic_ispanstream<char>;
304 using wispanstream = basic_ispanstream<wchar_t>;
306 template<typename _CharT, typename _Traits = char_traits<_CharT>>
307 class basic_ospanstream
308 : public basic_ostream<_CharT, _Traits>
310 using __ostream_type = basic_ostream<_CharT, _Traits>;
313 using char_type = _CharT;
314 using int_type = typename _Traits::int_type;
315 using pos_type = typename _Traits::pos_type;
316 using off_type = typename _Traits::off_type;
317 using traits_type = _Traits;
319 // [ospanstream.ctor], constructors
321 basic_ospanstream(std::span<_CharT> __s,
322 ios_base::openmode __which = ios_base::out)
323 : __ostream_type(std::__addressof(_M_sb)),
324 _M_sb(__s, __which | ios_base::in)
327 basic_ospanstream(const basic_ospanstream&) = delete;
329 basic_ospanstream(basic_ospanstream&& __rhs)
330 : __ostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
332 __ostream_type::set_rdbuf(std::addressof(_M_sb));
335 // [ospanstream.assign], assignment and swap
336 basic_ospanstream& operator=(const basic_ospanstream&) = delete;
337 basic_ospanstream& operator=(basic_ospanstream&& __rhs) = default;
340 swap(basic_ospanstream& __rhs)
342 __ostream_type::swap(__rhs);
343 _M_sb.swap(__rhs._M_sb);
346 // [ospanstream.members], member functions
347 basic_spanbuf<_CharT, _Traits>*
348 rdbuf() const noexcept
350 return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
354 span() const noexcept
355 { return _M_sb.span(); }
358 span(std::span<_CharT> __s) noexcept
359 { return _M_sb.span(__s); }
362 basic_spanbuf<_CharT, _Traits> _M_sb;
365 template<typename _CharT, typename _Traits>
367 swap(basic_ospanstream<_CharT, _Traits>& __x,
368 basic_ospanstream<_CharT, _Traits>& __y)
371 using ospanstream = basic_ospanstream<char>;
372 using wospanstream = basic_ospanstream<wchar_t>;
374 template<typename _CharT, typename _Traits = char_traits<_CharT>>
375 class basic_spanstream
376 : public basic_iostream<_CharT, _Traits>
378 using __iostream_type = basic_iostream<_CharT, _Traits>;
381 using char_type = _CharT;
382 using int_type = typename _Traits::int_type;
383 using pos_type = typename _Traits::pos_type;
384 using off_type = typename _Traits::off_type;
385 using traits_type = _Traits;
387 // [spanstream.ctor], constructors
389 basic_spanstream(std::span<_CharT> __s,
390 ios_base::openmode __which = ios_base::out | ios_base::in)
391 : __iostream_type(std::__addressof(_M_sb)),
395 basic_spanstream(const basic_spanstream&) = delete;
397 basic_spanstream(basic_spanstream&& __rhs)
398 : __iostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
400 __iostream_type::set_rdbuf(std::addressof(_M_sb));
403 // [spanstream.assign], assignment and swap
404 basic_spanstream& operator=(const basic_spanstream&) = delete;
405 basic_spanstream& operator=(basic_spanstream&& __rhs) = default;
408 swap(basic_spanstream& __rhs)
410 __iostream_type::swap(__rhs);
411 _M_sb.swap(__rhs._M_sb);
414 // [spanstream.members], members
415 basic_spanbuf<_CharT, _Traits>*
416 rdbuf() const noexcept
418 return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
422 span() const noexcept
423 { return _M_sb.span(); }
426 span(std::span<_CharT> __s) noexcept
427 { return _M_sb.span(__s); }
430 basic_spanbuf<_CharT, _Traits> _M_sb;
433 template<typename _CharT, typename _Traits>
435 swap(basic_spanstream<_CharT, _Traits>& __x,
436 basic_spanstream<_CharT, _Traits>& __y)
439 using spanstream = basic_spanstream<char>;
440 using wspanstream = basic_spanstream<wchar_t>;
442 _GLIBCXX_END_NAMESPACE_VERSION
444 #endif // __cpp_lib_span
446 #endif // _GLIBCXX_SPANSTREAM