Daily bump.
[official-gcc.git] / libstdc++-v3 / include / std / spanstream
blob240866ff26fcc42df272ee007e9e518f6815b96d
1 // Streams based on std::span -*- C++ -*-
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.
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/>.
25 /** @file spanstream
26  *  This is a Standard C++ Library header.
27  */
29 #ifndef _GLIBCXX_SPANSTREAM
30 #define _GLIBCXX_SPANSTREAM 1
32 #pragma GCC system_header
34 #if __cplusplus > 202002L
35 #include <span>
36 #include <streambuf>
37 #include <istream>
38 #include <ostream>
39 #include <bits/ranges_base.h>
41 #if __cpp_lib_span
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>>
49   class basic_spanbuf
50   : public basic_streambuf<_CharT, _Traits>
51   {
52     using __streambuf_type = basic_streambuf<_CharT, _Traits>;
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;
61     // [spanbuf.ctor], constructors
62     basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out)
63     { }
65     explicit
66     basic_spanbuf(ios_base::openmode __which)
67     : __streambuf_type(), _M_mode(__which)
68     { }
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); }
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;
86     basic_spanbuf&
87     operator=(basic_spanbuf&& __rhs)
88     {
89       basic_spanbuf(std::move(__rhs))->swap(*this);
90       return *this;
91     }
93     void
94     swap(basic_spanbuf& __rhs)
95     {
96       __streambuf_type::swap(__rhs);
97       std::swap(_M_mode, __rhs._M_mode);
98       std::swap(_M_buf, __rhs._M_buf);
99     }
101     // [spanbuf.members], member functions
102     std::span<_CharT>
103     span() const noexcept
104     {
105       if (_M_mode & ios_base::out)
106         return {this->pbase(), this->pptr()};
107       else
108         return _M_buf;
109     }
111     void
112     span(std::span<_CharT> __s) noexcept
113     {
114       _M_buf = __s;
115       if (_M_mode & ios_base::out)
116         {
117           this->setp(__s.data(), __s.data() + __s.size());
118           if (_M_mode & ios_base::ate)
119             this->pbump(__s.size());
120         }
121       if (_M_mode & ios_base::in)
122         this->setg(__s.data(), __s.data(), __s.data() + __s.size());
123     }
125   protected:
126     // [spanbuf.virtuals], overridden virtual functions
127     basic_streambuf<_CharT, _Traits>*
128     setbuf(_CharT* __s, streamsize __n) override
129     {
130       span({__s, __n});
131       return this;
132     }
134     pos_type
135     seekoff(off_type __off, ios_base::seekdir __way,
136             ios_base::openmode __which = ios_base::in | ios_base::out) override
137     {
138       pos_type __ret =  pos_type(off_type(-1));
140       if (__way == ios_base::beg)
141         {
142           if (0 <= __off && __off <= _M_buf.size())
143             {
144               if (__which & ios_base::in)
145                 this->setg(this->eback(), this->eback() + __off, this->egptr());
147               if (__which & ios_base::out)
148                 {
149                   this->setp(this->pbase(), this->epptr());
150                   this->pbump(__off);
151                 }
153               __ret = pos_type(__off);
154             }
155         }
156       else
157         {
158           off_type __base;
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)
164             {
165               if (__which == ios_base::in)
166                 __base = this->gptr() - this->eback();
167               else
168                 return __ret;
169             }
170           else if (__way == ios_base::end)
171             __base = _M_buf.size();
173           if (__builtin_add_overflow(__base, __off, &__off))
174             return __ret;
176           if (__off < 0 || __off > _M_buf.size())
177             return __ret;
179           if (__which & ios_base::in)
180             this->setg(this->eback(), this->eback() + __off, this->egptr());
182           if (__which & ios_base::out)
183             {
184               this->setp(this->pbase(), this->epptr());
185               this->pbump(__off);
186             }
188           __ret = pos_type(__off);
190         }
191       return __ret;
192     }
194     pos_type
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); }
199   private:
201     ios_base::openmode _M_mode;
202     std::span<_CharT> _M_buf;
203   };
205 template<typename _CharT, typename _Traits>
206   inline void
207   swap(basic_spanbuf<_CharT, _Traits>& __x,
208        basic_spanbuf<_CharT, _Traits>& __y)
209   { __x.swap(__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>
217   {
218     using __istream_type = basic_istream<_CharT, _Traits>;
220   public:
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
228     explicit
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)
233     { }
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))
239     {
240       __istream_type::set_rdbuf(std::addressof(_M_sb));
241     }
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>>
247       explicit
248       basic_ispanstream(_Ros&& __s)
249       : __istream_type(std::__addressof(_M_sb)),
250         _M_sb(ios_base::in)
251       {
252         std::span<const _CharT> __sp(std::forward<_Ros>(__s));
253         _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
254       }
256     // [ispanstream.assign], assignment and swap
257     basic_ispanstream& operator=(const basic_ispanstream&) = delete;
258     basic_ispanstream& operator=(basic_ispanstream&& __rhs) = default;
260     void
261     swap(basic_ispanstream& __rhs)
262     {
263       __istream_type::swap(__rhs);
264       _M_sb.swap(__rhs._M_sb);
265     }
267     // [ispanstream.members], member functions
268     basic_spanbuf<_CharT, _Traits>*
269     rdbuf() const noexcept
270     {
271       return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
272     }
274     std::span<const _CharT>
275     span() const noexcept
276     { return _M_sb.span(); }
278     void
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>>
286       void
287       span(_Ros&& __s) noexcept
288       {
289         std::span<const _CharT> __sp(std::forward<_Ros>(__s));
290         _M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
291       }
293   private:
294     basic_spanbuf<_CharT, _Traits> _M_sb;
295   };
297 template<typename _CharT, typename _Traits>
298   inline void
299   swap(basic_ispanstream<_CharT, _Traits>& __x,
300        basic_ispanstream<_CharT, _Traits>& __y)
301   { __x.swap(__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>
309   {
310     using __ostream_type = basic_ostream<_CharT, _Traits>;
312   public:
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
320     explicit
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)
325     { }
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))
331     {
332       __ostream_type::set_rdbuf(std::addressof(_M_sb));
333     }
335     // [ospanstream.assign], assignment and swap
336     basic_ospanstream& operator=(const basic_ospanstream&) = delete;
337     basic_ospanstream& operator=(basic_ospanstream&& __rhs) = default;
339     void
340     swap(basic_ospanstream& __rhs)
341     {
342       __ostream_type::swap(__rhs);
343       _M_sb.swap(__rhs._M_sb);
344     }
346     // [ospanstream.members], member functions
347     basic_spanbuf<_CharT, _Traits>*
348     rdbuf() const noexcept
349     {
350       return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
351     }
353     std::span<_CharT>
354     span() const noexcept
355     { return _M_sb.span(); }
357     void
358     span(std::span<_CharT> __s) noexcept
359     { return _M_sb.span(__s); }
361   private:
362     basic_spanbuf<_CharT, _Traits> _M_sb;
363   };
365 template<typename _CharT, typename _Traits>
366   inline void
367   swap(basic_ospanstream<_CharT, _Traits>& __x,
368        basic_ospanstream<_CharT, _Traits>& __y)
369   { __x.swap(__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>
377   {
378     using __iostream_type = basic_iostream<_CharT, _Traits>;
380   public:
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
388     explicit
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)),
392       _M_sb(__s, __which)
393     { }
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))
399     {
400       __iostream_type::set_rdbuf(std::addressof(_M_sb));
401     }
403     // [spanstream.assign], assignment and swap
404     basic_spanstream& operator=(const basic_spanstream&) = delete;
405     basic_spanstream& operator=(basic_spanstream&& __rhs) = default;
407     void
408     swap(basic_spanstream& __rhs)
409     {
410       __iostream_type::swap(__rhs);
411       _M_sb.swap(__rhs._M_sb);
412     }
414     // [spanstream.members], members
415     basic_spanbuf<_CharT, _Traits>*
416     rdbuf() const noexcept
417     {
418       return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
419     }
421     std::span<_CharT>
422     span() const noexcept
423     { return _M_sb.span(); }
425     void
426     span(std::span<_CharT> __s) noexcept
427     { return _M_sb.span(__s); }
429   private:
430     basic_spanbuf<_CharT, _Traits> _M_sb;
431   };
433 template<typename _CharT, typename _Traits>
434   inline void
435   swap(basic_spanstream<_CharT, _Traits>& __x,
436        basic_spanstream<_CharT, _Traits>& __y)
437   { __x.swap(__y); }
439 using spanstream = basic_spanstream<char>;
440 using wspanstream = basic_spanstream<wchar_t>;
442 _GLIBCXX_END_NAMESPACE_VERSION
443 } // namespace std
444 #endif // __cpp_lib_span
445 #endif // C++23
446 #endif // _GLIBCXX_SPANSTREAM