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