source: mainline/uspace/lib/cpp/include/impl/ios.hpp@ 05922b3b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 05922b3b was 05922b3b, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: fixed goodbit value

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