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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since bc56f30 was bc56f30, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Make some libc and libposix headers usable in C++

These headers either get included from standard C++ headers,
or are standard themselves, which means any unnamespaced nonstandard
identifiers are a problem. This commit attempts to fix those
issues, and removes hacks previously used in libcpp to work around it.

  • Property mode set to 100644
File size: 17.1 KB
Line 
1/*
2 * Copyright (c) 2018 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_BITS_IO_IOS
30#define LIBCPP_BITS_IO_IOS
31
32#include <__bits/locale/locale.hpp>
33#include <__bits/locale/ctype.hpp>
34#include <cstdlib>
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 private:
218 static constexpr size_t buffer_size_{64};
219 char buffer_[buffer_size_];
220
221 template<class Char, class Iterator>
222 friend class num_put;
223
224 template<class Char, class Iterator>
225 friend class num_get;
226 };
227
228 /**
229 * 27.5.4, fpos:
230 */
231
232 template<class State>
233 class fpos
234 {
235 public:
236 State state() const
237 {
238 return state_;
239 }
240
241 void state(State st)
242 {
243 state_ = st;
244 }
245
246 private:
247 State state_;
248 };
249
250 /**
251 * 27.5.4.2, fpos requirements:
252 */
253
254 // TODO: implement
255
256 /**
257 * 27.5.5, basic_ios:
258 */
259
260 template<class Char, class Traits>
261 class basic_ios: public ios_base
262 {
263 public:
264 using traits_type = Traits;
265 using char_type = Char;
266 using int_type = typename traits_type::int_type;
267 using pos_type = typename traits_type::pos_type;
268 using off_type = typename traits_type::off_type;
269
270 basic_ios(const basic_ios&) = delete;
271 basic_ios& operator=(const basic_ios&) = delete;
272
273 explicit operator bool() const
274 {
275 return !fail();
276 }
277
278 bool operator!() const
279 {
280 return fail();
281 }
282
283 iostate rdstate() const
284 {
285 return rdstate_;
286 }
287
288 void clear(iostate state = goodbit)
289 {
290 if (rdbuf_)
291 rdstate_ = state;
292 else
293 rdstate_ = state | badbit;
294
295 if (((state | (rdbuf_ ? goodbit : badbit)) & exceptions_) == 0)
296 return;
297 // TODO: Else throw failure.
298 return;
299 }
300
301 void setstate(iostate state)
302 {
303 clear(rdstate_ | state);
304 }
305
306 bool good() const
307 {
308 return rdstate_ == 0;
309 }
310
311 bool eof() const
312 {
313 return (rdstate_ & eofbit) != 0;
314 }
315
316 bool fail() const
317 {
318 return (rdstate_ & (failbit | badbit)) != 0;
319 }
320
321 bool bad() const
322 {
323 return (rdstate_ & badbit) != 0;
324 }
325
326 iostate exceptions() const
327 {
328 return exceptions_;
329 }
330
331 void exceptions(iostate except)
332 {
333 exceptions_ = except;
334 clear(rdstate_);
335 }
336
337 /**
338 * 27.5.5.2, constructor/destructor:
339 */
340
341 explicit basic_ios(basic_streambuf<Char, Traits>* sb)
342 {
343 init(sb);
344 }
345
346 virtual ~basic_ios()
347 { /* DUMMY BODY */ }
348
349 /**
350 * 27.5.5.3, members:
351 */
352
353 basic_ostream<Char, Traits>* tie() const
354 {
355 return tie_;
356 }
357
358 basic_ostream<Char, Traits>* tie(basic_ostream<Char, Traits>* tiestr)
359 {
360 auto old = tie_;
361 tie_ = tiestr;
362
363 return old;
364 }
365
366 basic_streambuf<Char, Traits>* rdbuf() const
367 {
368 return rdbuf_;
369 }
370
371 basic_streambuf<Char, Traits>* rdbuf(basic_streambuf<Char, Traits>* sb)
372 {
373 auto old = rdbuf_;
374 rdbuf_ = sb;
375
376 clear();
377
378 return old;
379 }
380
381 basic_ios& copyfmt(const basic_ios& rhs)
382 {
383 if (this == &rhs)
384 return *this;
385
386 for (auto& callback: callbacks_)
387 callback.first(erase_event, *this, index_);
388
389 tie_ = rhs.tie_;
390 flags_ = rhs.flags_;
391 width_ = rhs.width_;
392 precision_ = rhs.precision_;
393 fill_ = rhs.fill_;
394 locale_ = rhs.locale_;
395
396 delete[] iarray_;
397 iarray_size_ = rhs.iarray_size_;
398 iarray_ = new long[iarray_size_];
399
400 for (size_t i = 0; i < iarray_size_; ++i)
401 iarray_[i] = rhs.iarray_[i];
402
403 delete[] parray_;
404 parray_size_ = rhs.parray_size_;
405 parray_ = new long[parray_size_];
406
407 for (size_t i = 0; i < parray_size_; ++i)
408 parray_[i] = rhs.parray_[i];
409
410 for (auto& callback: callbacks_)
411 callback.first(copyfmt_event, *this, index_);
412
413 exceptions(rhs.exceptions());
414 }
415
416 char_type fill() const
417 {
418 return fill_;
419 }
420
421 char_type fill(char_type c)
422 {
423 char_type old;
424 traits_type::assign(old, fill_);
425 traits_type::assign(fill_, c);
426
427 return old;
428 }
429
430 locale imbue(const locale& loc)
431 {
432 auto res = ios_base::imbue(loc);
433
434 if (rdbuf_)
435 rdbuf_->pubimbue(loc);
436
437 return res;
438 }
439
440 char narrow(char_type c, char def) const
441 {
442 return use_facet<ctype<char_type>>(locale_).narrow(c, def);
443 }
444
445 char_type widen(char c) const
446 {
447 return use_facet<ctype<char_type>>(locale_).widen(c);
448 }
449
450 protected:
451 basic_ios()
452 { /* DUMMY BODY */ }
453
454 void init(basic_streambuf<Char, Traits>* sb)
455 {
456 // Initialized according to Table 128.
457 rdbuf_ = sb;
458 tie_ = nullptr;
459 rdstate_ = sb ? goodbit : badbit;
460 exceptions_ = goodbit;
461 flags(skipws | dec);
462
463 width(0);
464 precision(6);
465
466 fill_ = widen(' ');
467 locale_ = locale();
468
469 iarray_ = nullptr;
470 parray_ = nullptr;
471 }
472
473 void move(basic_ios& rhs)
474 {
475 rdbuf_ = nullptr; // rhs keeps it!
476 tie_ = rhs.tie_;
477 exceptions_ = rhs.exceptions_;
478 flags_ = rhs.flags_;
479 width_ = rhs.width_;
480 precision_ = rhs.precision_;
481 fill_ = rhs.fill_;
482 locale_ = move(rhs.locale_);
483 rdstate_ = rhs.rdstate_;
484 callbacks_ = move(rhs.callbacks_);
485
486 delete[] iarray_;
487 iarray_ = rhs.iarray_;
488 iarray_size_ = rhs.iarray_size_;
489
490 delete[] parray_;
491 parray_ = rhs.parray_;
492 parray_size_ = rhs.parray_size_;
493
494 rhs.tie_ = nullptr;
495 rhs.iarray_ = nullptr;
496 rhs.parray_ = nullptr;
497 }
498
499 void move(basic_ios&& rhs)
500 {
501 rdbuf_ = nullptr; // rhs keeps it!
502 tie_ = rhs.tie_;
503 exceptions_ = rhs.exceptions_;
504 flags_ = rhs.flags_;
505 width_ = rhs.width_;
506 precision_ = rhs.precision_;
507 fill_ = rhs.fill_;
508 locale_ = move(rhs.locale_);
509 rdstate_ = rhs.rdstate_;
510 callbacks_.swap(rhs.callbacks_);
511
512 delete[] iarray_;
513 iarray_ = rhs.iarray_;
514 iarray_size_ = rhs.iarray_size_;
515
516 delete[] parray_;
517 parray_ = rhs.parray_;
518 parray_size_ = rhs.parray_size_;
519
520 rhs.tie_ = nullptr;
521 rhs.iarray_ = nullptr;
522 rhs.parray_ = nullptr;
523 }
524
525 void swap(basic_ios& rhs) noexcept
526 {
527 // Swap everything but rdbuf_.
528 swap(tie_, rhs.tie_);
529 swap(exceptions_, rhs.exceptions_);
530 swap(flags_, rhs.flags_);
531 swap(width_, rhs.width_);
532 swap(precision_, rhs.precision_);
533 swap(fill_, rhs.fill_);
534 swap(locale_, rhs.locale_);
535 swap(rdstate_, rhs.rdstate_);
536 swap(callbacks_, rhs.callbacks_);
537 swap(iarray_);
538 swap(iarray_size_);
539 swap(parray_);
540 swap(parray_size_);
541 }
542
543 void set_rdbuf(basic_streambuf<Char, Traits>* sb)
544 {
545 // No call to clear is intentional.
546 rdbuf_ = sb;
547 }
548
549 private:
550 basic_streambuf<Char, Traits>* rdbuf_;
551 basic_ostream<Char, Traits>* tie_;
552 iostate rdstate_;
553 iostate exceptions_;
554 char_type fill_;
555 };
556
557 /**
558 * 27.5.6, ios_base manipulators:
559 */
560
561 /**
562 * 27.5.6.1, fmtflags manipulators:
563 */
564
565 ios_base& boolalpha(ios_base& str);
566 ios_base& noboolalpha(ios_base& str);
567 ios_base& showbase(ios_base& str);
568 ios_base& noshowbase(ios_base& str);
569 ios_base& showpoint(ios_base& str);
570 ios_base& noshowpoint(ios_base& str);
571 ios_base& showpos(ios_base& str);
572 ios_base& noshowpos(ios_base& str);
573 ios_base& skipws(ios_base& str);
574 ios_base& noskipws(ios_base& str);
575 ios_base& uppercase(ios_base& str);
576 ios_base& nouppercase(ios_base& str);
577 ios_base& unitbuf(ios_base& str);
578 ios_base& nounitbuf(ios_base& str);
579
580 /**
581 * 27.5.6.2, adjustfield manipulators:
582 */
583
584 ios_base& internal(ios_base& str);
585 ios_base& left(ios_base& str);
586 ios_base& right(ios_base& str);
587
588 /**
589 * 27.5.6.3, basefield manupulators:
590 */
591
592 ios_base& dec(ios_base& str);
593 ios_base& hex(ios_base& str);
594 ios_base& oct(ios_base& str);
595
596 /**
597 * 27.5.6.4, floatfield manupulators:
598 */
599
600 ios_base& fixed(ios_base& str);
601 ios_base& scientific(ios_base& str);
602 ios_base& hexfloat(ios_base& str);
603 ios_base& defaultfloat(ios_base& str);
604
605 /**
606 * 27.5.6.5, error reporting:
607 */
608
609 // TODO: implement
610}
611
612#endif
Note: See TracBrowser for help on using the repository browser.