source: mainline/uspace/lib/cpp/include/__bits/io/sstream.hpp@ 8fd0675f

Last change on this file since 8fd0675f was b57ba05, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update headers in C++ files

  • Property mode set to 100644
File size: 16.7 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2018 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef LIBCPP_BITS_IO_SSTREAM
8#define LIBCPP_BITS_IO_SSTREAM
9
10#include <ios>
11#include <iosfwd>
12#include <iostream>
13#include <streambuf>
14#include <string>
15
16namespace std
17{
18 /**
19 * 27.8.2, class template basic_stringbuf:
20 */
21
22 template<class Char, class Traits, class Allocator>
23 class basic_stringbuf: public basic_streambuf<Char, Traits>
24 {
25 public:
26 using char_type = Char;
27 using traits_type = Traits;
28 using allocator_type = Allocator;
29 using int_type = typename traits_type::int_type;
30 using pos_type = typename traits_type::pos_type;
31 using off_type = typename traits_type::off_type;
32
33 /**
34 * 27.8.2.1, constructors:
35 */
36
37 explicit basic_stringbuf(ios_base::openmode mode = ios_base::in | ios_base::out)
38 : basic_streambuf<char_type, traits_type>(), mode_{mode}, str_{}
39 {
40 init_();
41 }
42
43 explicit basic_stringbuf(const basic_string<char_type, traits_type, allocator_type> str,
44 ios_base::openmode mode = ios_base::in | ios_base::out)
45 : basic_streambuf<char_type, traits_type>(), mode_{mode}, str_{str}
46 {
47 init_();
48 }
49
50 basic_stringbuf(const basic_stringbuf&) = delete;
51
52 basic_stringbuf(basic_stringbuf&& other)
53 : mode_{move(other.mode_)}, str_{move(other.str_)}
54 {
55 basic_streambuf<char_type, traits_type>::swap(other);
56 }
57
58 /**
59 * 27.8.2.2, assign and swap:
60 */
61
62 basic_stringbuf& operator=(const basic_stringbuf&) = delete;
63
64 basic_stringbuf& operator=(basic_stringbuf&& other)
65 {
66 swap(other);
67 }
68
69 void swap(basic_stringbuf& rhs)
70 {
71 std::swap(mode_, rhs.mode_);
72 std::swap(str_, rhs.str_);
73
74 basic_streambuf<char_type, traits_type>::swap(rhs);
75 }
76
77 /**
78 * 27.8.2.3, get and set:
79 */
80
81 basic_string<char_type, traits_type, allocator_type> str() const
82 {
83 if (mode_ & ios_base::out)
84 return basic_string<char_type, traits_type, allocator_type>{
85 this->output_begin_, this->output_next_ - 1, str_.get_allocator()
86 };
87 else if (mode_ == ios_base::in)
88 return basic_string<char_type, traits_type, allocator_type>{
89 this->eback(), this->egptr(), str_.get_allocator()
90 };
91 else
92 return basic_string<char_type, traits_type, allocator_type>{};
93 }
94
95 void str(const basic_string<char_type, traits_type, allocator_type>& str)
96 {
97 str_ = str;
98 init_();
99 }
100
101 protected:
102 /**
103 * 27.8.2.4, overriden virtual functions:
104 */
105
106 int_type underflow() override
107 {
108 if (this->read_avail_())
109 return traits_type::to_int_type(*this->gptr());
110 else
111 return traits_type::eof();
112 }
113
114 int_type pbackfail(int_type c = traits_type::eof()) override
115 {
116 if (!traits_type::eq_int_type(c, traits_type::eof()) &&
117 this->putback_avail_() &&
118 traits_type::eq(traits_type::to_char_type(c), this->gptr()[-1]))
119 {
120 --this->input_next_;
121
122 return c;
123 }
124 else if (!traits_type::eq_int_type(c, traits_type::eof()) &&
125 this->putback_avail_() && (mode_ & ios_base::out) != 0)
126 {
127 *--this->input_next_ = c;
128
129 return c;
130 }
131 else if (traits_type::eq_int_type(c, traits_type::eof()) &&
132 this->putback_avail_())
133 {
134 --this->input_next_;
135
136 return traits_type::not_eof(c);
137 }
138
139 return traits_type::eof();
140 }
141
142 int_type overflow(int_type c = traits_type::eof()) override
143 {
144 if ((mode_ & ios_base::out) == 0)
145 return traits_type::eof();
146
147 if (!traits_type::eq_int_type(c, traits_type::eof()))
148 {
149 if (this->output_next_ < this->output_end_)
150 return c;
151
152 auto size = static_cast<size_t>(this->output_next_ - this->output_begin_);
153 str_.size_ = size;
154
155 str_.push_back(traits_type::to_char_type(c));
156 init_();
157
158 return c;
159 }
160 else if (traits_type::eq_int_type(c, traits_type::eof()))
161 return traits_type::not_eof(c);
162
163 return traits_type::eof();
164 }
165
166 basic_streambuf<char_type, traits_type>* setbuf(char_type* str, streamsize n) override
167 {
168 if (!str && n == 0)
169 return this;
170
171 str_.assign(str, str + static_cast<size_t>(n));
172
173 return this;
174 }
175
176 pos_type seekoff(off_type off, ios_base::seekdir dir,
177 ios_base::openmode mode = ios_base::in | ios_base::out)
178 {
179 if ((mode & ios_base::in) == ios_base::in)
180 {
181 if (!this->input_next_)
182 return pos_type(off_type(-1));
183
184 return seekoff_(off, this->input_begin_, this->input_next_, this->input_end_, dir);
185 }
186 else if ((mode & ios_base::out) == ios_base::out)
187 {
188 if (!this->output_next_)
189 return pos_type(off_type(-1));
190
191 return seekoff_(off, this->output_begin_, this->output_next_, this->output_end_, dir);
192 }
193 else if ((mode & (ios_base::in | ios_base::out)) == (ios_base::in | ios_base::out) &&
194 (dir == ios_base::beg || dir == ios_base::end))
195 {
196 if (!this->input_next_ || !this->output_next_)
197 return pos_type(off_type(-1));
198
199 seekoff_(off, this->input_begin_, this->input_next_, this->input_end_, dir);
200 return seekoff_(off, this->output_begin_, this->output_next_, this->output_end_, dir);
201 }
202
203 return pos_type(off_type(-1));
204 }
205
206 pos_type seekpos(pos_type pos, ios_base::openmode mode = ios_base::in | ios_base::out)
207 {
208 return seekoff(off_type(pos), ios_base::beg, mode);
209 }
210
211 private:
212 ios_base::openmode mode_;
213 basic_string<char_type, traits_type, allocator_type> str_;
214
215 void init_()
216 {
217 if ((mode_ & ios_base::in) != 0)
218 {
219 this->input_begin_ = this->input_next_ = str_.begin();
220 this->input_end_ = str_.end();
221 }
222
223 if ((mode_ & ios_base::out) != 0)
224 {
225 this->output_begin_ = str_.begin();
226 this->output_next_ = str_.end();
227 this->output_end_ = str_.begin() + str_.size() + 1;
228 }
229 }
230
231 bool ensure_free_space_(size_t n = 1)
232 {
233 str_.ensure_free_space_(n);
234 this->output_end_ = str_.begin() + str_.capacity();
235
236 return true;
237 }
238
239 pos_type seekoff_(off_type off, char_type* begin, char_type*& next, char_type* end,
240 ios_base::seekdir dir)
241 {
242 off_type new_off{};
243
244 if (dir == ios_base::beg)
245 new_off = 0;
246 else if (dir == ios_base::cur)
247 new_off = static_cast<off_type>(next - begin);
248 else if (dir == ios_base::end)
249 new_off = static_cast<off_type>(end - begin);
250
251 if (new_off + off < 0 || begin + new_off + off >= end)
252 return pos_type(off_type(-1));
253 else
254 next = begin + new_off + off;
255
256 return pos_type(new_off);
257 }
258 };
259
260 template<class Char, class Traits, class Allocator>
261 void swap(basic_stringbuf<Char, Traits, Allocator>& lhs,
262 basic_stringbuf<Char, Traits, Allocator>& rhs)
263 {
264 lhs.swap(rhs);
265 }
266
267 /**
268 * 27.8.3, class template basic_istringstream:
269 */
270
271 template<class Char, class Traits, class Allocator>
272 class basic_istringstream: public basic_istream<Char, Traits>
273 {
274 public:
275 using char_type = Char;
276 using traits_type = Traits;
277 using allocator_type = Allocator;
278 using int_type = typename traits_type::int_type;
279 using pos_type = typename traits_type::pos_type;
280 using off_type = typename traits_type::off_type;
281
282 /**
283 * 27.8.3.1, constructors:
284 */
285
286 explicit basic_istringstream(ios_base::openmode mode = ios_base::in)
287 : basic_istream<char_type, traits_type>(&sb_),
288 sb_(mode | ios_base::in)
289 { /* DUMMY BODY */ }
290
291 explicit basic_istringstream(const basic_string<char_type, traits_type, allocator_type> str,
292 ios_base::openmode mode = ios_base::in)
293 : basic_istream<char_type, traits_type>{&sb_},
294 sb_(str, mode | ios_base::in)
295 { /* DUMMY BODY */ }
296
297 basic_istringstream(const basic_istringstream&) = delete;
298
299 basic_istringstream(basic_istringstream&& other)
300 : basic_istream<char_type, traits_type>{move(other)},
301 sb_{move(other.sb_)}
302 {
303 basic_istream<char_type, traits_type>::set_rdbuf(&sb_);
304 }
305
306 /**
307 * 27.8.3.2, assign and swap:
308 */
309
310 basic_istringstream& operator=(const basic_istringstream&) = delete;
311
312 basic_istringstream& operator=(basic_istringstream&& other)
313 {
314 swap(other);
315 }
316
317 void swap(basic_istringstream& rhs)
318 {
319 basic_istream<char_type, traits_type>::swap(rhs);
320 sb_.swap(rhs.sb_);
321 }
322
323 /**
324 * 27.8.3.3, members:
325 */
326
327 basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const
328 {
329 return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&sb_);
330 }
331
332 basic_string<char_type, traits_type, allocator_type> str() const
333 {
334 return sb_.str();
335 }
336
337 void str(const basic_string<char_type, traits_type, allocator_type>& str)
338 {
339 sb_.str(str);
340 }
341
342 private:
343 basic_stringbuf<char_type, traits_type, allocator_type> sb_;
344 };
345
346 template<class Char, class Traits, class Allocator>
347 void swap(basic_istringstream<Char, Traits, Allocator>& lhs,
348 basic_istringstream<Char, Traits, Allocator>& rhs)
349 {
350 lhs.swap(rhs);
351 }
352
353 template<class Char, class Traits, class Allocator>
354 class basic_ostringstream: public basic_ostream<Char, Traits>
355 {
356 public:
357 using char_type = Char;
358 using traits_type = Traits;
359 using allocator_type = Allocator;
360 using int_type = typename traits_type::int_type;
361 using pos_type = typename traits_type::pos_type;
362 using off_type = typename traits_type::off_type;
363
364 /**
365 * 27.8.4.1, constructors:
366 */
367
368 explicit basic_ostringstream(ios_base::openmode mode = ios_base::out)
369 : basic_ostream<char_type, traits_type>(&sb_),
370 sb_(mode | ios_base::out)
371 { /* DUMMY BODY */ }
372
373 explicit basic_ostringstream(const basic_string<char_type, traits_type, allocator_type> str,
374 ios_base::openmode mode = ios_base::out)
375 : basic_ostream<char_type, traits_type>{&sb_},
376 sb_(str, mode | ios_base::out)
377 { /* DUMMY BODY */ }
378
379 basic_ostringstream(const basic_ostringstream&) = delete;
380
381 basic_ostringstream(basic_ostringstream&& other)
382 : basic_ostream<char_type, traits_type>{move(other)},
383 sb_{move(other.sb_)}
384 {
385 basic_ostream<char_type, traits_type>::set_rdbuf(&sb_);
386 }
387
388 /**
389 * 27.8.4.2, assign and swap:
390 */
391
392 basic_ostringstream& operator=(const basic_ostringstream&) = delete;
393
394 basic_ostringstream& operator=(basic_ostringstream&& other)
395 {
396 swap(other);
397 }
398
399 void swap(basic_ostringstream& rhs)
400 {
401 basic_ostream<char_type, traits_type>::swap(rhs);
402 sb_.swap(rhs.sb_);
403 }
404
405 /**
406 * 27.8.3.3, members:
407 */
408
409 basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const
410 {
411 return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&sb_);
412 }
413
414 basic_string<char_type, traits_type, allocator_type> str() const
415 {
416 return sb_.str();
417 }
418
419 void str(const basic_string<char_type, traits_type, allocator_type>& str)
420 {
421 sb_.str(str);
422 }
423
424 private:
425 basic_stringbuf<char_type, traits_type, allocator_type> sb_;
426 };
427
428 /**
429 * 27.8.5, class template basic_stringstream:
430 */
431
432 template<class Char, class Traits, class Allocator>
433 class basic_stringstream: public basic_iostream<Char, Traits>
434 {
435 public:
436 using char_type = Char;
437 using traits_type = Traits;
438 using allocator_type = Allocator;
439 using int_type = typename traits_type::int_type;
440 using pos_type = typename traits_type::pos_type;
441 using off_type = typename traits_type::off_type;
442
443 /**
444 * 27.8.5.1, constructors:
445 */
446
447 explicit basic_stringstream(ios_base::openmode mode = ios_base::in | ios_base::out)
448 : basic_iostream<char_type, traits_type>(&sb_),
449 sb_(mode | ios_base::out)
450 { /* DUMMY BODY */ }
451
452 explicit basic_stringstream(const basic_string<char_type, traits_type, allocator_type> str,
453 ios_base::openmode mode = ios_base::in | ios_base::out)
454 : basic_iostream<char_type, traits_type>{&sb_},
455 sb_(str, mode | ios_base::out)
456 { /* DUMMY BODY */ }
457
458 basic_stringstream(const basic_stringstream&) = delete;
459
460 basic_stringstream(basic_stringstream&& other)
461 : basic_iostream<char_type, traits_type>{move(other)},
462 sb_{move(other.sb_)}
463 {
464 basic_iostream<char_type, traits_type>::set_rdbuf(&sb_);
465 }
466
467 /**
468 * 27.8.5.2, assign and swap:
469 */
470
471 basic_stringstream& operator=(const basic_stringstream&) = delete;
472
473 basic_stringstream& operator=(basic_stringstream&& other)
474 {
475 swap(other);
476 }
477
478 void swap(basic_stringstream& rhs)
479 {
480 basic_iostream<char_type, traits_type>::swap(rhs);
481 sb_.swap(rhs.sb_);
482 }
483
484 /**
485 * 27.8.5.3, members:
486 */
487
488 basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const
489 {
490 return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&sb_);
491 }
492
493 basic_string<char_type, traits_type, allocator_type> str() const
494 {
495 return sb_.str();
496 }
497
498 void str(const basic_string<char_type, traits_type, allocator_type>& str)
499 {
500 sb_.str(str);
501 }
502
503 private:
504 basic_stringbuf<char_type, traits_type, allocator_type> sb_;
505 };
506}
507
508#endif
Note: See TracBrowser for help on using the repository browser.