source: mainline/uspace/lib/cpp/include/__bits/io/ostream.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: 22.6 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2019 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef LIBCPP_BITS_IO_OSTREAM
8#define LIBCPP_BITS_IO_OSTREAM
9
10#include <cassert>
11#include <ios>
12#include <iosfwd>
13#include <locale>
14
15namespace std
16{
17 /**
18 * 27.7.3.1, class template basic_ostream:
19 */
20
21 template<class Char, class Traits>
22 class basic_ostream: virtual public basic_ios<Char, Traits>
23 {
24 public:
25 using char_type = Char;
26 using traits_type = Traits;
27 using int_type = typename traits_type::int_type;
28 using pos_type = typename traits_type::pos_type;
29 using off_type = typename traits_type::off_type;
30
31 /**
32 * 27.7.3.2, constructor/destructor:
33 */
34
35 explicit basic_ostream(basic_streambuf<char_type, traits_type>* sb)
36 {
37 basic_ios<Char, Traits>::init(sb);
38 }
39
40 virtual ~basic_ostream()
41 { /* DUMMY BODY */ }
42
43 /**
44 * 27.7.3.4, prefix/suffix:
45 */
46
47 class sentry
48 {
49 public:
50 explicit sentry(basic_ostream<Char, Traits>& os)
51 : os_{os}, ok_{false}
52 {
53 if (os.good())
54 {
55 if (os.tie())
56 os.tie()->flush();
57 }
58
59 ok_ = os.good();
60 }
61
62 ~sentry()
63 {
64 if ((os_.flags() & ios_base::unitbuf) && os_.good())
65 {
66 auto ret = os_.rdbuf()->pubsync();
67 (void)ret;
68 // TODO: if ret == -1, set badbit in rdstate
69 }
70 }
71
72 explicit operator bool() const
73 {
74 return ok_;
75 }
76
77 sentry(const sentry&) = delete;
78 sentry& operator=(const sentry&) = delete;
79
80 private:
81 basic_ostream<Char, Traits>& os_;
82 bool ok_;
83 };
84
85 /**
86 * 27.7.3.6, formatted output:
87 */
88
89 basic_ostream<Char, Traits>& operator<<(
90 basic_ostream<Char, Traits>& (*pf)(basic_ostream<Char, Traits>&)
91 )
92 {
93 return pf(*this);
94 }
95
96 basic_ostream<Char, Traits>& operator<<(
97 basic_ios<Char, Traits>& (*pf)(basic_ios<Char, Traits>&)
98 )
99 {
100 pf(*this);
101
102 return *this;
103 }
104
105 basic_ostream<Char, Traits>& operator<<(
106 ios_base& (*pf)(ios_base&)
107 )
108 {
109 pf(*this);
110
111 return *this;
112 }
113
114 basic_ostream<Char, Traits>& operator<<(bool x)
115 {
116 sentry sen{*this};
117
118 if (sen)
119 {
120 bool failed = use_facet<
121 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
122 >(this->getloc()).put(*this, *this, this->fill(), x).failed();
123
124 if (failed)
125 this->setstate(ios_base::badbit);
126 }
127
128 return *this;
129 }
130
131 basic_ostream<Char, Traits>& operator<<(short x)
132 {
133 sentry sen{*this};
134
135 if (sen)
136 {
137 auto basefield = (this->flags() & ios_base::basefield);
138 bool failed = use_facet<
139 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
140 >(this->getloc()).put(*this, *this, this->fill(),
141 (basefield == ios_base::oct || basefield == ios_base::hex)
142 ? static_cast<long>(static_cast<unsigned short>(x))
143 : static_cast<long>(x)).failed();
144
145 if (failed)
146 this->setstate(ios_base::badbit);
147 }
148
149 return *this;
150 }
151
152 basic_ostream<Char, Traits>& operator<<(unsigned short x)
153 {
154 sentry sen{*this};
155
156 if (sen)
157 {
158 bool failed = use_facet<
159 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
160 >(this->getloc()).put(*this, *this, this->fill(),
161 static_cast<unsigned long>(x)).failed();
162
163 if (failed)
164 this->setstate(ios_base::badbit);
165 }
166
167 return *this;
168 }
169
170 basic_ostream<Char, Traits>& operator<<(int x)
171 {
172 sentry sen{*this};
173
174 if (sen)
175 {
176 auto basefield = (this->flags() & ios_base::basefield);
177 bool failed = use_facet<
178 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
179 >(this->getloc()).put(*this, *this, this->fill(),
180 (basefield == ios_base::oct || basefield == ios_base::hex)
181 ? static_cast<long>(static_cast<unsigned int>(x))
182 : static_cast<long>(x)).failed();
183
184 if (failed)
185 this->setstate(ios_base::badbit);
186 }
187
188 return *this;
189 }
190
191 basic_ostream<Char, Traits>& operator<<(unsigned int x)
192 {
193 sentry sen{*this};
194
195 if (sen)
196 {
197 bool failed = use_facet<
198 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
199 >(this->getloc()).put(*this, *this, this->fill(),
200 static_cast<unsigned long>(x)).failed();
201
202 if (failed)
203 this->setstate(ios_base::badbit);
204 }
205
206 return *this;
207 }
208
209 basic_ostream<Char, Traits>& operator<<(long x)
210 {
211 sentry sen{*this};
212
213 if (sen)
214 {
215 bool failed = use_facet<
216 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
217 >(this->getloc()).put(*this, *this, this->fill(), x).failed();
218
219 if (failed)
220 this->setstate(ios_base::badbit);
221 }
222
223 return *this;
224 }
225
226 basic_ostream<Char, Traits>& operator<<(unsigned long x)
227 {
228 sentry sen{*this};
229
230 if (sen)
231 {
232 bool failed = use_facet<
233 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
234 >(this->getloc()).put(*this, *this, this->fill(), x).failed();
235
236 if (failed)
237 this->setstate(ios_base::badbit);
238 }
239
240 return *this;
241 }
242
243 basic_ostream<Char, Traits>& operator<<(long long x)
244 {
245 sentry sen{*this};
246
247 if (sen)
248 {
249 bool failed = use_facet<
250 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
251 >(this->getloc()).put(*this, *this, this->fill(), x).failed();
252
253 if (failed)
254 this->setstate(ios_base::badbit);
255 }
256
257 return *this;
258 }
259
260 basic_ostream<Char, Traits>& operator<<(unsigned long long x)
261 {
262 sentry sen{*this};
263
264 if (sen)
265 {
266 bool failed = use_facet<
267 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
268 >(this->getloc()).put(*this, *this, this->fill(), x).failed();
269
270 if (failed)
271 this->setstate(ios_base::badbit);
272 }
273
274 return *this;
275 }
276
277 basic_ostream<Char, Traits>& operator<<(float x)
278 {
279 sentry sen{*this};
280
281 if (sen)
282 {
283 bool failed = use_facet<
284 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
285 >(this->getloc()).put(*this, *this, this->fill(), static_cast<double>(x)).failed();
286
287 if (failed)
288 this->setstate(ios_base::badbit);
289 }
290
291 return *this;
292 }
293
294 basic_ostream<Char, Traits>& operator<<(double x)
295 {
296 sentry sen{*this};
297
298 if (sen)
299 {
300 bool failed = use_facet<
301 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
302 >(this->getloc()).put(*this, *this, this->fill(), x).failed();
303
304 if (failed)
305 this->setstate(ios_base::badbit);
306 }
307
308 return *this;
309 }
310
311 basic_ostream<Char, Traits>& operator<<(long double x)
312 {
313 sentry sen{*this};
314
315 if (sen)
316 {
317 bool failed = use_facet<
318 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
319 >(this->getloc()).put(*this, *this, this->fill(), x).failed();
320
321 if (failed)
322 this->setstate(ios_base::badbit);
323 }
324
325 return *this;
326 }
327
328 basic_ostream<Char, Traits>& operator<<(const void* p)
329 {
330 sentry sen{*this};
331
332 if (sen)
333 {
334 bool failed = use_facet<
335 num_put<char_type, ostreambuf_iterator<char_type, traits_type>>
336 >(this->getloc()).put(*this, *this, this->fill(), p).failed();
337
338 if (failed)
339 this->setstate(ios_base::badbit);
340 }
341
342 return *this;
343 }
344
345 basic_ostream<Char, Traits>& operator<<(basic_streambuf<Char, Traits>* sb)
346 {
347 if (!sb)
348 return *this;
349
350 sentry sen{*this};
351
352 if (sen)
353 {
354 size_t count{};
355
356 int_type c = sb->sgetc();
357 while (!traits_type::eq_int_type(c, traits_type::eof()))
358 {
359 this->put(traits_type::to_char_type(c));
360
361 if (!(*this))
362 break;
363
364 ++count;
365 sb->sbumpc();
366 c = sb->sgetc();
367 }
368
369 if (count == 0)
370 this->setstate(ios_base::failbit);
371 }
372
373 return *this;
374 }
375
376 /**
377 * 27.7.3.7, unformatted output:
378 * TODO: when we have exceptions, complete these
379 */
380
381 basic_ostream<Char, Traits>& put(char_type c)
382 {
383 sentry sen{*this};
384
385 if (sen)
386 {
387 auto ret = this->rdbuf()->sputc(c);
388 if (traits_type::eq_int_type(ret, traits_type::eof()))
389 this->setstate(ios_base::badbit);
390 }
391
392 return *this;
393 }
394
395 basic_ostream<Char, Traits>& write(const char_type* s, streamsize n)
396 {
397 sentry sen{*this};
398
399 if (sen)
400 {
401 for (streamsize i = 0; i < n; ++i)
402 {
403 auto ret = this->rdbuf()->sputc(s[i]);
404 if (traits_type::eq_int_type(ret, traits_type::eof()))
405 {
406 this->setstate(ios_base::badbit);
407 break;
408 }
409 }
410 }
411
412 return *this;
413 }
414
415 basic_ostream<Char, Traits>& flush()
416 {
417 if (this->rdbuf())
418 {
419 sentry sen{*this};
420
421 if (sen)
422 {
423 auto ret = this->rdbuf()->pubsync();
424 if (ret == -1)
425 this->setstate(ios_base::badbit);
426 }
427 }
428
429 return *this;
430 }
431
432 /**
433 * 27.7.3.5, seeks:
434 */
435
436 pos_type tellp()
437 {
438 // TODO: implement
439 __unimplemented();
440 return pos_type{};
441 }
442
443 basic_ostream<Char, Traits>& seekp(pos_type pos)
444 {
445 // TODO: implement
446 __unimplemented();
447 return *this;
448 }
449
450 basic_ostream<Char, Traits>& seekp(off_type off, ios_base::seekdir dir)
451 {
452 // TODO: implement
453 __unimplemented();
454 return *this;
455 }
456
457 protected:
458 basic_ostream(const basic_ostream&) = delete;
459
460 basic_ostream(basic_ostream&& other)
461 {
462 basic_ios<Char, Traits>::move(other);
463 }
464
465 /**
466 * 27.7.3.3, assign/swap:
467 */
468
469 basic_ostream& operator=(const basic_ostream&) = delete;
470
471 basic_ostream& operator=(basic_ostream&& other)
472 {
473 swap(other);
474
475 return *this;
476 }
477
478 void swap(basic_ostream& rhs)
479 {
480 basic_ios<Char, Traits>::swap(rhs);
481 }
482 };
483
484 using ostream = basic_ostream<char>;
485 using wostream = basic_ostream<wchar_t>;
486
487 /**
488 * 27.7.6.3.4, character inserter function templates:
489 */
490
491 template<class Char, class Traits>
492 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os,
493 Char c)
494 {
495 typename basic_ostream<Char, Traits>::sentry sen{os};
496
497 if (sen)
498 {
499 if (os.width() > 0)
500 {
501 if ((os.flags() & ios_base::adjustfield) != ios_base::left)
502 {
503 for (decltype(os.width()) i = 0; i < os.width(); ++i)
504 os.put(os.fill());
505 os.put(c);
506 }
507 else
508 {
509 os.put(c);
510 for (decltype(os.width()) i = 0; i < os.width(); ++i)
511 os.put(os.fill());
512 }
513 }
514 else
515 os.put(c);
516
517 os.width(0);
518 }
519
520 return os;
521 }
522
523 template<class Char, class Traits>
524 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os,
525 char c)
526 {
527 typename basic_ostream<Char, Traits>::sentry sen{os};
528
529 if (sen)
530 {
531 if (os.width() > 0)
532 {
533 if ((os.flags() & ios_base::adjustfield) != ios_base::left)
534 {
535 for (decltype(os.width()) i = 0; i < os.width(); ++i)
536 os.put(os.fill());
537 os.put(os.widen(c));
538 }
539 else
540 {
541 os.put(os.widen(c));
542 for (decltype(os.width()) i = 0; i < os.width(); ++i)
543 os.put(os.fill());
544 }
545 }
546 else
547 os.put(os.widen(c));
548
549 os.width(0);
550 }
551 return os;
552 }
553
554 template<class Traits>
555 basic_ostream<char, Traits>& operator<<(basic_ostream<char, Traits>& os,
556 char c)
557 {
558 typename basic_ostream<char, Traits>::sentry sen{os};
559
560 if (sen)
561 {
562 if (os.width() > 0)
563 {
564 if ((os.flags() & ios_base::adjustfield) != ios_base::left)
565 {
566 for (decltype(os.width()) i = 0; i < os.width(); ++i)
567 os.put(os.fill());
568 os.put(c);
569 }
570 else
571 {
572 os.put(c);
573 for (decltype(os.width()) i = 0; i < os.width(); ++i)
574 os.put(os.fill());
575 }
576 }
577 else
578 os.put(c);
579
580 os.width(0);
581 }
582
583 return os;
584 }
585
586 template<class Traits>
587 basic_ostream<char, Traits>& operator<<(basic_ostream<char, Traits>& os,
588 signed char c)
589 {
590 typename basic_ostream<char, Traits>::sentry sen{os};
591
592 if (sen)
593 {
594 if (os.width() > 0)
595 {
596 if ((os.flags() & ios_base::adjustfield) != ios_base::left)
597 {
598 for (decltype(os.width()) i = 0; i < os.width(); ++i)
599 os.put(os.fill());
600 os.put(c);
601 }
602 else
603 {
604 os.put(c);
605 for (decltype(os.width()) i = 0; i < os.width(); ++i)
606 os.put(os.fill());
607 }
608 }
609 else
610 os.put(c);
611
612 os.width(0);
613 }
614
615 return os;
616 }
617
618 template<class Traits>
619 basic_ostream<char, Traits>& operator<<(basic_ostream<char, Traits>& os,
620 unsigned char c)
621 {
622 typename basic_ostream<char, Traits>::sentry sen{os};
623
624 if (sen)
625 {
626 if (os.width() > 0)
627 {
628 if ((os.flags() & ios_base::adjustfield) != ios_base::left)
629 {
630 for (decltype(os.width()) i = 0; i < os.width(); ++i)
631 os.put(os.fill());
632 os.put(c);
633 }
634 else
635 {
636 os.put(c);
637 for (decltype(os.width()) i = 0; i < os.width(); ++i)
638 os.put(os.fill());
639 }
640 }
641 else
642 os.put(c);
643
644 os.width(0);
645 }
646
647 return os;
648 }
649
650 namespace aux
651 {
652 template<class Char, class Traits>
653 basic_ostream<Char, Traits>& insert(basic_ostream<Char, Traits>& os,
654 const Char* str, size_t len)
655 {
656 if (os.width() > 0 && static_cast<size_t>(os.width()) > len)
657 {
658 size_t to_pad = (static_cast<size_t>(os.width()) - len);
659
660 if ((os.flags() & ios_base::adjustfield) != ios_base::left)
661 {
662 for (size_t i = 0; i < to_pad; ++i)
663 os.put(os.fill());
664 for (size_t i = 0; i < len; ++i)
665 os.put(os.widen(str[i]));
666 }
667 else
668 {
669 for (size_t i = 0; i < len; ++i)
670 os.put(os.widen(str[i]));
671 for (size_t i = 0; i < to_pad; ++i)
672 os.put(os.fill());
673 }
674 }
675 else
676 {
677 for (size_t i = 0; i < len; ++i)
678 os.put(os.widen(str[i]));
679 }
680
681 os.width(0);
682 return os;
683 }
684 }
685
686 template<class Char, class Traits>
687 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os,
688 const Char* str)
689 {
690 typename basic_ostream<Char, Traits>::sentry sen{os};
691
692 auto len = Traits::length(str);
693
694 return aux::insert(os, str, len);
695 }
696
697 template<class Char, class Traits>
698 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os,
699 const char* str)
700 {
701 typename basic_ostream<Char, Traits>::sentry sen{os};
702
703 auto len = std::char_traits<char>::length(str);
704
705 return aux::insert(os, str, len);
706 }
707
708 template<class Traits>
709 basic_ostream<char, Traits>& operator<<(basic_ostream<char, Traits>& os,
710 const char* str)
711 {
712 typename basic_ostream<char, Traits>::sentry sen{os};
713
714 if (sen)
715 {
716 auto len = Traits::length(str);
717
718 return aux::insert(os, str, len);
719 }
720 else
721 return os;
722 }
723
724 template<class Traits>
725 basic_ostream<char, Traits>& operator<<(basic_ostream<char, Traits>& os,
726 const signed char* str)
727 {
728 typename basic_ostream<char, Traits>::sentry sen{os};
729
730 if (sen)
731 {
732 auto len = Traits::length(reinterpret_cast<const char*>(str));
733
734 return aux::insert(os, str, len);
735 }
736 else
737 return os;
738 }
739
740 template<class Traits>
741 basic_ostream<char, Traits>& operator<<(basic_ostream<char, Traits>& os,
742 const unsigned char* str)
743 {
744 typename basic_ostream<char, Traits>::sentry sen{os};
745
746 if (sen)
747 {
748 auto len = Traits::length(reinterpret_cast<const char*>(str));
749
750 return aux::insert(os, str, len);
751 }
752 else
753 return os;
754 }
755
756 /**
757 * 27.7.3.8, standard basic_ostream manipulators:
758 */
759
760 template<class Char, class Traits = char_traits<Char>>
761 basic_ostream<Char, Traits>& endl(basic_ostream<Char, Traits>& os)
762 {
763 os.put(os.widen('\n'));
764 os.flush();
765
766 return os;
767 }
768
769 template<class Char, class Traits = char_traits<Char>>
770 basic_ostream<Char, Traits>& ends(basic_ostream<Char, Traits>& os)
771 {
772 os.put(Char{});
773
774 return os;
775 }
776
777 template<class Char, class Traits = char_traits<Char>>
778 basic_ostream<Char, Traits>& flush(basic_ostream<Char, Traits>& os)
779 {
780 os.flush();
781
782 return os;
783 }
784
785 template<class Char, class Traits = char_traits<Char>, class T>
786 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>&& os, const T& x)
787 {
788 os << x;
789
790 return os;
791 }
792}
793
794#endif
795
Note: See TracBrowser for help on using the repository browser.