source: mainline/uspace/lib/cpp/include/internal/streambufs.hpp@ 7258487

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

cpp: implemented basic stdin & stdout streambufs

  • Property mode set to 100644
File size: 5.5 KB
RevLine 
[7258487]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_STREAMBUFS
30#define LIBCPP_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 auto ic = traits_type::to_int_type(c);
85 if (traits_type::eq_int_type(ic, traits_type::eof()))
86 break;
87
88 buffer_[i] = c;
89
90 if (c == '\n')
91 break;
92 }
93
94 input_next_ = input_begin_;
95 input_end_ = input_begin_ + i;
96
97 if (i == 0)
98 return traits_type::eof();
99
100 return traits_type::to_int_type(*input_next_);
101 }
102
103 int_type uflow() override
104 {
105 // TODO: what is the difference between uflow and underflow?
106 auto res = underflow();
107 ++*input_next_;
108
109 return res;
110 }
111
112 void imbue(const locale& loc)
113 {
114 this->locale_ = loc;
115 }
116
117 private:
118 FILE* in_{stdin};
119
120 char_type* buffer_;
121
122 static constexpr off_type buf_size_{128};
123 };
124
125 template<class Char, class Traits = char_traits<Char>>
126 class stdout_streambuf: public basic_streambuf<Char, Traits>
127 {
128 public:
129 stdout_streambuf()
130 : basic_streambuf<Char, Traits>{}
131 { /* DUMMY BODY */ }
132
133 virtual ~stdout_streambuf()
134 { /* DUMMY BODY */ }
135
136 protected:
137 using traits_type = Traits;
138 using char_type = typename traits_type::char_type;
139 using int_type = typename traits_type::int_type;
140 using off_type = typename traits_type::off_type;
141
142 int_type overflow(int_type c = traits_type::eof()) override
143 {
144 if (!traits_type::eq_int_type(c, traits_type::eof()))
145 {
146 auto cc = traits_type::to_char_type(c);
147 fwrite(&cc, sizeof(char_type), 1, out_);
148 }
149
150 return traits_type::not_eof(c);
151 }
152
153 streamsize xsputn(const char_type* s, streamsize n) override
154 {
155 return fwrite(s, sizeof(char_type), n, out_);
156 }
157
158 int sync() override
159 {
160 if (fflush(out_))
161 return -1;
162 return 0;
163 }
164
165 private:
166 FILE* out_{stdout};
167 };
168}
169
170#endif
Note: See TracBrowser for help on using the repository browser.