source: mainline/uspace/lib/cpp/include/__bits/io/ios.hpp@ 8624d1f

Last change on this file since 8624d1f 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: 15.8 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2018 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef LIBCPP_BITS_IO_IOS
8#define LIBCPP_BITS_IO_IOS
9
10#include <__bits/locale/locale.hpp>
11#include <__bits/locale/ctype.hpp>
12#include <cstdlib>
13#include <iosfwd>
14#include <system_error>
15#include <utility>
16#include <vector>
17
18namespace std
19{
20 using streamoff = long long;
21 using streamsize = ::ssize_t;
22
23 /**
24 * 27.5.3, ios_base:
25 */
26
27 class ios_base
28 {
29 public:
30 virtual ~ios_base();
31
32 ios_base(const ios_base&) = delete;
33 ios_base& operator=(const ios_base&) = delete;
34
35 /**
36 * 27.5.3.1.1, failure:
37 */
38
39 class failure: public system_error
40 {
41 // TODO: implement
42 };
43
44 /**
45 * 27.5.3.1.2, fmtflags:
46 */
47
48 using fmtflags = uint16_t;
49 static constexpr fmtflags boolalpha = 0b0000'0000'0000'0001;
50 static constexpr fmtflags dec = 0b0000'0000'0000'0010;
51 static constexpr fmtflags fixed = 0b0000'0000'0000'0100;
52 static constexpr fmtflags hex = 0b0000'0000'0000'1000;
53 static constexpr fmtflags internal = 0b0000'0000'0001'0000;
54 static constexpr fmtflags left = 0b0000'0000'0010'0000;
55 static constexpr fmtflags oct = 0b0000'0000'0100'0000;
56 static constexpr fmtflags right = 0b0000'0000'1000'0000;
57 static constexpr fmtflags scientific = 0b0000'0001'0000'0000;
58 static constexpr fmtflags showbase = 0b0000'0010'0000'0000;
59 static constexpr fmtflags showpoint = 0b0000'0100'0000'0000;
60 static constexpr fmtflags showpos = 0b0000'1000'0000'0000;
61 static constexpr fmtflags skipws = 0b0001'0000'0000'0000;
62 static constexpr fmtflags unitbuf = 0b0010'0000'0000'0000;
63 static constexpr fmtflags uppercase = 0b0100'0000'0000'0000;
64 static constexpr fmtflags adjustfield = left | right | internal;
65 static constexpr fmtflags basefield = dec | oct | hex;
66 static constexpr fmtflags floatfield = scientific | fixed;
67
68 /**
69 * 27.5.3.1.3, iostate:
70 */
71
72 using iostate = uint8_t;
73 static constexpr iostate badbit = 0b0001;
74 static constexpr iostate eofbit = 0b0010;
75 static constexpr iostate failbit = 0b0100;
76 static constexpr iostate goodbit = 0b0000;
77
78 /**
79 * 27.5.3.1.4, openmode:
80 */
81
82 using openmode = uint8_t;
83 static constexpr openmode app = 0b00'0001;
84 static constexpr openmode ate = 0b00'0010;
85 static constexpr openmode binary = 0b00'0100;
86 static constexpr openmode in = 0b00'1000;
87 static constexpr openmode out = 0b01'0000;
88 static constexpr openmode trunc = 0b10'0000;
89
90 /**
91 * 27.5.3.1.5, seekdir:
92 */
93
94 using seekdir = uint8_t;
95 static constexpr seekdir beg = 0b001;
96 static constexpr seekdir cur = 0b010;
97 static constexpr seekdir end = 0b100;
98
99 /**
100 * 27.5.3.1.6, class Init:
101 */
102
103 class Init
104 {
105 public:
106 Init();
107 ~Init();
108
109 private:
110 static int init_cnt_;
111 };
112
113 /**
114 * 27.5.3.2, fmtflags state:
115 */
116
117 fmtflags flags() const;
118 fmtflags flags(fmtflags fmtfl);
119 fmtflags setf(fmtflags fmtfl);
120 fmtflags setf(fmtflags fmtfl, fmtflags mask);
121 void unsetf(fmtflags mask);
122
123 streamsize precision() const;
124 streamsize precision(streamsize prec);
125 streamsize width() const;
126 streamsize width(streamsize wide);
127
128 /**
129 * 27.5.3.3, locales:
130 */
131
132 locale imbue(const locale& loc);
133 locale getloc() const;
134
135 /**
136 * 27.5.3.5, storage:
137 */
138
139 static int xalloc()
140 {
141 // TODO: Concurrent access to this function
142 // by multiple threads shall not result
143 // in a data race.
144 return index_++;
145 }
146
147 long& iword(int index);
148 void*& pword(int index);
149
150 /**
151 * 27.5.3.6, callbacks:
152 */
153
154 enum event
155 {
156 erase_event,
157 imbue_event,
158 copyfmt_event
159 };
160
161 using event_callback = void (*)(event, ios_base&, int);
162 void register_callback(event_callback fn, int index);
163
164 static bool sync_with_stdio(bool sync = true)
165 {
166 auto old = sync_;
167 sync_ = sync;
168
169 return old;
170 }
171
172 protected:
173 ios_base();
174
175 static int index_;
176 static bool sync_;
177
178 static long ierror_;
179 static void* perror_;
180 static constexpr size_t initial_size_{10};
181
182 long* iarray_;
183 void** parray_;
184 size_t iarray_size_;
185 size_t parray_size_;
186
187 fmtflags flags_;
188 streamsize precision_;
189 streamsize width_;
190
191 locale locale_;
192
193 vector<pair<event_callback, int>> callbacks_;
194
195 private:
196 static constexpr size_t buffer_size_{64};
197 char buffer_[buffer_size_];
198
199 template<class Char, class Iterator>
200 friend class num_put;
201
202 template<class Char, class Iterator>
203 friend class num_get;
204 };
205
206 /**
207 * 27.5.4, fpos:
208 */
209
210 template<class State>
211 class fpos
212 {
213 public:
214 State state() const
215 {
216 return state_;
217 }
218
219 void state(State st)
220 {
221 state_ = st;
222 }
223
224 private:
225 State state_;
226 };
227
228 /**
229 * 27.5.4.2, fpos requirements:
230 */
231
232 // TODO: implement
233
234 /**
235 * 27.5.5, basic_ios:
236 */
237
238 template<class Char, class Traits>
239 class basic_ios: public ios_base
240 {
241 public:
242 using traits_type = Traits;
243 using char_type = Char;
244 using int_type = typename traits_type::int_type;
245 using pos_type = typename traits_type::pos_type;
246 using off_type = typename traits_type::off_type;
247
248 basic_ios(const basic_ios&) = delete;
249 basic_ios& operator=(const basic_ios&) = delete;
250
251 explicit operator bool() const
252 {
253 return !fail();
254 }
255
256 bool operator!() const
257 {
258 return fail();
259 }
260
261 iostate rdstate() const
262 {
263 return rdstate_;
264 }
265
266 void clear(iostate state = goodbit)
267 {
268 if (rdbuf_)
269 rdstate_ = state;
270 else
271 rdstate_ = state | badbit;
272
273 if (((state | (rdbuf_ ? goodbit : badbit)) & exceptions_) == 0)
274 return;
275 // TODO: Else throw failure.
276 return;
277 }
278
279 void setstate(iostate state)
280 {
281 clear(rdstate_ | state);
282 }
283
284 bool good() const
285 {
286 return rdstate_ == 0;
287 }
288
289 bool eof() const
290 {
291 return (rdstate_ & eofbit) != 0;
292 }
293
294 bool fail() const
295 {
296 return (rdstate_ & (failbit | badbit)) != 0;
297 }
298
299 bool bad() const
300 {
301 return (rdstate_ & badbit) != 0;
302 }
303
304 iostate exceptions() const
305 {
306 return exceptions_;
307 }
308
309 void exceptions(iostate except)
310 {
311 exceptions_ = except;
312 clear(rdstate_);
313 }
314
315 /**
316 * 27.5.5.2, constructor/destructor:
317 */
318
319 explicit basic_ios(basic_streambuf<Char, Traits>* sb)
320 {
321 init(sb);
322 }
323
324 virtual ~basic_ios()
325 { /* DUMMY BODY */ }
326
327 /**
328 * 27.5.5.3, members:
329 */
330
331 basic_ostream<Char, Traits>* tie() const
332 {
333 return tie_;
334 }
335
336 basic_ostream<Char, Traits>* tie(basic_ostream<Char, Traits>* tiestr)
337 {
338 auto old = tie_;
339 tie_ = tiestr;
340
341 return old;
342 }
343
344 basic_streambuf<Char, Traits>* rdbuf() const
345 {
346 return rdbuf_;
347 }
348
349 basic_streambuf<Char, Traits>* rdbuf(basic_streambuf<Char, Traits>* sb)
350 {
351 auto old = rdbuf_;
352 rdbuf_ = sb;
353
354 clear();
355
356 return old;
357 }
358
359 basic_ios& copyfmt(const basic_ios& rhs)
360 {
361 if (this == &rhs)
362 return *this;
363
364 for (auto& callback: callbacks_)
365 callback.first(erase_event, *this, index_);
366
367 tie_ = rhs.tie_;
368 flags_ = rhs.flags_;
369 width_ = rhs.width_;
370 precision_ = rhs.precision_;
371 fill_ = rhs.fill_;
372 locale_ = rhs.locale_;
373
374 delete[] iarray_;
375 iarray_size_ = rhs.iarray_size_;
376 iarray_ = new long[iarray_size_];
377
378 for (size_t i = 0; i < iarray_size_; ++i)
379 iarray_[i] = rhs.iarray_[i];
380
381 delete[] parray_;
382 parray_size_ = rhs.parray_size_;
383 parray_ = new long[parray_size_];
384
385 for (size_t i = 0; i < parray_size_; ++i)
386 parray_[i] = rhs.parray_[i];
387
388 for (auto& callback: callbacks_)
389 callback.first(copyfmt_event, *this, index_);
390
391 exceptions(rhs.exceptions());
392 }
393
394 char_type fill() const
395 {
396 return fill_;
397 }
398
399 char_type fill(char_type c)
400 {
401 char_type old;
402 traits_type::assign(old, fill_);
403 traits_type::assign(fill_, c);
404
405 return old;
406 }
407
408 locale imbue(const locale& loc)
409 {
410 auto res = ios_base::imbue(loc);
411
412 if (rdbuf_)
413 rdbuf_->pubimbue(loc);
414
415 return res;
416 }
417
418 char narrow(char_type c, char def) const
419 {
420 return use_facet<ctype<char_type>>(locale_).narrow(c, def);
421 }
422
423 char_type widen(char c) const
424 {
425 return use_facet<ctype<char_type>>(locale_).widen(c);
426 }
427
428 protected:
429 basic_ios()
430 { /* DUMMY BODY */ }
431
432 void init(basic_streambuf<Char, Traits>* sb)
433 {
434 // Initialized according to Table 128.
435 rdbuf_ = sb;
436 tie_ = nullptr;
437 rdstate_ = sb ? goodbit : badbit;
438 exceptions_ = goodbit;
439 flags(skipws | dec);
440
441 width(0);
442 precision(6);
443
444 fill_ = widen(' ');
445 locale_ = locale();
446
447 iarray_ = nullptr;
448 parray_ = nullptr;
449 }
450
451 void move(basic_ios& rhs)
452 {
453 rdbuf_ = nullptr; // rhs keeps it!
454 tie_ = rhs.tie_;
455 exceptions_ = rhs.exceptions_;
456 flags_ = rhs.flags_;
457 width_ = rhs.width_;
458 precision_ = rhs.precision_;
459 fill_ = rhs.fill_;
460 locale_ = move(rhs.locale_);
461 rdstate_ = rhs.rdstate_;
462 callbacks_ = move(rhs.callbacks_);
463
464 delete[] iarray_;
465 iarray_ = rhs.iarray_;
466 iarray_size_ = rhs.iarray_size_;
467
468 delete[] parray_;
469 parray_ = rhs.parray_;
470 parray_size_ = rhs.parray_size_;
471
472 rhs.tie_ = nullptr;
473 rhs.iarray_ = nullptr;
474 rhs.parray_ = nullptr;
475 }
476
477 void move(basic_ios&& rhs)
478 {
479 rdbuf_ = nullptr; // rhs keeps it!
480 tie_ = rhs.tie_;
481 exceptions_ = rhs.exceptions_;
482 flags_ = rhs.flags_;
483 width_ = rhs.width_;
484 precision_ = rhs.precision_;
485 fill_ = rhs.fill_;
486 locale_ = move(rhs.locale_);
487 rdstate_ = rhs.rdstate_;
488 callbacks_.swap(rhs.callbacks_);
489
490 delete[] iarray_;
491 iarray_ = rhs.iarray_;
492 iarray_size_ = rhs.iarray_size_;
493
494 delete[] parray_;
495 parray_ = rhs.parray_;
496 parray_size_ = rhs.parray_size_;
497
498 rhs.tie_ = nullptr;
499 rhs.iarray_ = nullptr;
500 rhs.parray_ = nullptr;
501 }
502
503 void swap(basic_ios& rhs) noexcept
504 {
505 // Swap everything but rdbuf_.
506 swap(tie_, rhs.tie_);
507 swap(exceptions_, rhs.exceptions_);
508 swap(flags_, rhs.flags_);
509 swap(width_, rhs.width_);
510 swap(precision_, rhs.precision_);
511 swap(fill_, rhs.fill_);
512 swap(locale_, rhs.locale_);
513 swap(rdstate_, rhs.rdstate_);
514 swap(callbacks_, rhs.callbacks_);
515 swap(iarray_);
516 swap(iarray_size_);
517 swap(parray_);
518 swap(parray_size_);
519 }
520
521 void set_rdbuf(basic_streambuf<Char, Traits>* sb)
522 {
523 // No call to clear is intentional.
524 rdbuf_ = sb;
525 }
526
527 private:
528 basic_streambuf<Char, Traits>* rdbuf_;
529 basic_ostream<Char, Traits>* tie_;
530 iostate rdstate_;
531 iostate exceptions_;
532 char_type fill_;
533 };
534
535 /**
536 * 27.5.6, ios_base manipulators:
537 */
538
539 /**
540 * 27.5.6.1, fmtflags manipulators:
541 */
542
543 ios_base& boolalpha(ios_base& str);
544 ios_base& noboolalpha(ios_base& str);
545 ios_base& showbase(ios_base& str);
546 ios_base& noshowbase(ios_base& str);
547 ios_base& showpoint(ios_base& str);
548 ios_base& noshowpoint(ios_base& str);
549 ios_base& showpos(ios_base& str);
550 ios_base& noshowpos(ios_base& str);
551 ios_base& skipws(ios_base& str);
552 ios_base& noskipws(ios_base& str);
553 ios_base& uppercase(ios_base& str);
554 ios_base& nouppercase(ios_base& str);
555 ios_base& unitbuf(ios_base& str);
556 ios_base& nounitbuf(ios_base& str);
557
558 /**
559 * 27.5.6.2, adjustfield manipulators:
560 */
561
562 ios_base& internal(ios_base& str);
563 ios_base& left(ios_base& str);
564 ios_base& right(ios_base& str);
565
566 /**
567 * 27.5.6.3, basefield manupulators:
568 */
569
570 ios_base& dec(ios_base& str);
571 ios_base& hex(ios_base& str);
572 ios_base& oct(ios_base& str);
573
574 /**
575 * 27.5.6.4, floatfield manupulators:
576 */
577
578 ios_base& fixed(ios_base& str);
579 ios_base& scientific(ios_base& str);
580 ios_base& hexfloat(ios_base& str);
581 ios_base& defaultfloat(ios_base& str);
582
583 /**
584 * 27.5.6.5, error reporting:
585 */
586
587 // TODO: implement
588}
589
590#endif
Note: See TracBrowser for help on using the repository browser.