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

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

cpp: fixed minor bugs that prevented ios from compilation

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