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