source: mainline/uspace/lib/cpp/include/__bits/io/streambufs.hpp

Last change on this file was b57a3ee, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: refactored the library layout, everything from the impl directory was moved to the bits directory for the sake of consistency, updated copyright notices and include guards

  • Property mode set to 100644
File size: 5.4 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_STREAMBUFS
30#define LIBCPP_BITS_IO_STREAMBUFS
31
32#include <iosfwd>
33#include <cstdio>
34#include <streambuf>
35
36namespace std::aux
37{
38 template<class Char, class Traits = char_traits<Char>>
39 class stdin_streambuf : public basic_streambuf<Char, Traits>
40 {
41 public:
42 stdin_streambuf()
43 : basic_streambuf<Char, Traits>{}, buffer_{nullptr}
44 { /* DUMMY BODY */ }
45
46 virtual ~stdin_streambuf()
47 {
48 if (buffer_)
49 delete[] buffer_;
50 }
51
52 protected:
53 using traits_type = Traits;
54 using char_type = typename traits_type::char_type;
55 using int_type = typename traits_type::int_type;
56 using off_type = typename traits_type::off_type;
57
58 using basic_streambuf<Char, Traits>::input_begin_;
59 using basic_streambuf<Char, Traits>::input_next_;
60 using basic_streambuf<Char, Traits>::input_end_;
61
62 int_type underflow() override
63 {
64 if (!this->gptr())
65 {
66 buffer_ = new char_type[buf_size_];
67 input_begin_ = input_next_ = input_end_ = buffer_;
68 }
69
70 off_type i{};
71 if (input_next_ < input_end_)
72 {
73 auto idx = static_cast<off_type>(input_next_ - input_begin_);
74 auto count = buf_size_ - idx;
75
76 for (; i < count; ++i, ++idx)
77 buffer_[i] = buffer_[idx];
78 }
79
80 for (; i < buf_size_; ++i)
81 {
82 auto c = fgetc(in_);
83 putchar(c); // TODO: Temporary source of feedback.
84 if (c == traits_type::eof())
85 break;
86
87 buffer_[i] = static_cast<char_type>(c);
88
89 if (buffer_[i] == '\n')
90 {
91 ++i;
92 break;
93 }
94 }
95
96 input_next_ = input_begin_;
97 input_end_ = input_begin_ + i;
98
99 if (i == 0)
100 return traits_type::eof();
101
102 return traits_type::to_int_type(*input_next_);
103 }
104
105 int_type uflow() override
106 {
107 auto res = underflow();
108 ++input_next_;
109
110 return res;
111 }
112
113 void imbue(const locale& loc)
114 {
115 this->locale_ = loc;
116 }
117
118 private:
119 FILE* in_{stdin};
120
121 char_type* buffer_;
122
123 static constexpr off_type buf_size_{128};
124 };
125
126 template<class Char, class Traits = char_traits<Char>>
127 class stdout_streambuf: public basic_streambuf<Char, Traits>
128 {
129 public:
130 stdout_streambuf()
131 : basic_streambuf<Char, Traits>{}
132 { /* DUMMY BODY */ }
133
134 virtual ~stdout_streambuf()
135 { /* DUMMY BODY */ }
136
137 protected:
138 using traits_type = Traits;
139 using char_type = typename traits_type::char_type;
140 using int_type = typename traits_type::int_type;
141 using off_type = typename traits_type::off_type;
142
143 int_type overflow(int_type c = traits_type::eof()) override
144 {
145 if (!traits_type::eq_int_type(c, traits_type::eof()))
146 {
147 auto cc = traits_type::to_char_type(c);
148 fwrite(&cc, sizeof(char_type), 1, out_);
149 }
150
151 return traits_type::not_eof(c);
152 }
153
154 streamsize xsputn(const char_type* s, streamsize n) override
155 {
156 return fwrite(s, sizeof(char_type), n, out_);
157 }
158
159 int sync() override
160 {
161 if (fflush(out_))
162 return -1;
163 return 0;
164 }
165
166 private:
167 FILE* out_{stdout};
168 };
169}
170
171#endif
Note: See TracBrowser for help on using the repository browser.