source: mainline/uspace/lib/cpp/include/impl/ios.hpp@ 54939b27

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

cpp: implemented ios_base manipulators

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