1 | // |
2 | // UnufferedStreamBuf.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Streams |
6 | // Module: StreamBuf |
7 | // |
8 | // Definition of template BasicUnbufferedStreamBuf and class UnbufferedStreamBuf. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_UnbufferedStreamBuf_INCLUDED |
18 | #define Foundation_UnbufferedStreamBuf_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/StreamUtil.h" |
23 | #include <streambuf> |
24 | #include <iosfwd> |
25 | #include <ios> |
26 | |
27 | |
28 | namespace Poco { |
29 | |
30 | |
31 | template <typename ch, typename tr> |
32 | class BasicUnbufferedStreamBuf: public std::basic_streambuf<ch, tr> |
33 | /// This is an implementation of an unbuffered streambuf |
34 | /// that greatly simplifies the implementation of |
35 | /// custom streambufs of various kinds. |
36 | /// Derived classes only have to override the methods |
37 | /// readFromDevice() or writeToDevice(). |
38 | { |
39 | protected: |
40 | typedef std::basic_streambuf<ch, tr> Base; |
41 | typedef std::basic_ios<ch, tr> IOS; |
42 | typedef ch char_type; |
43 | typedef tr char_traits; |
44 | typedef typename Base::int_type int_type; |
45 | typedef typename Base::pos_type pos_type; |
46 | typedef typename Base::off_type off_type; |
47 | typedef typename IOS::openmode openmode; |
48 | |
49 | public: |
50 | BasicUnbufferedStreamBuf(): |
51 | _pb(char_traits::eof()), |
52 | _ispb(false) |
53 | { |
54 | this->setg(0, 0, 0); |
55 | this->setp(0, 0); |
56 | } |
57 | |
58 | ~BasicUnbufferedStreamBuf() |
59 | { |
60 | } |
61 | |
62 | virtual int_type overflow(int_type c) |
63 | { |
64 | if (c != char_traits::eof()) |
65 | return writeToDevice(char_traits::to_char_type(c)); |
66 | else |
67 | return c; |
68 | } |
69 | |
70 | virtual int_type underflow() |
71 | { |
72 | if (_ispb) |
73 | { |
74 | return _pb; |
75 | } |
76 | else |
77 | { |
78 | int_type c = readFromDevice(); |
79 | if (c != char_traits::eof()) |
80 | { |
81 | _ispb = true; |
82 | _pb = c; |
83 | } |
84 | return c; |
85 | } |
86 | } |
87 | |
88 | virtual int_type uflow() |
89 | { |
90 | if (_ispb) |
91 | { |
92 | _ispb = false; |
93 | return _pb; |
94 | } |
95 | else |
96 | { |
97 | int_type c = readFromDevice(); |
98 | if (c != char_traits::eof()) |
99 | { |
100 | _pb = c; |
101 | } |
102 | return c; |
103 | } |
104 | } |
105 | |
106 | virtual int_type pbackfail(int_type c) |
107 | { |
108 | if (_ispb) |
109 | { |
110 | return char_traits::eof(); |
111 | } |
112 | else |
113 | { |
114 | _ispb = true; |
115 | _pb = c; |
116 | return c; |
117 | } |
118 | } |
119 | |
120 | virtual std::streamsize xsgetn(char_type* p, std::streamsize count) |
121 | /// Some platforms (for example, Compaq C++) have buggy implementations of |
122 | /// xsgetn that handle null buffers incorrectly. |
123 | /// Anyway, it does not hurt to provide an optimized implementation |
124 | /// of xsgetn for this streambuf implementation. |
125 | { |
126 | std::streamsize copied = 0; |
127 | while (count > 0) |
128 | { |
129 | int_type c = uflow(); |
130 | if (c == char_traits::eof()) break; |
131 | *p++ = char_traits::to_char_type(c); |
132 | ++copied; |
133 | --count; |
134 | } |
135 | return copied; |
136 | } |
137 | |
138 | protected: |
139 | static int_type charToInt(char_type c) |
140 | { |
141 | return char_traits::to_int_type(c); |
142 | } |
143 | |
144 | private: |
145 | virtual int_type readFromDevice() |
146 | { |
147 | return char_traits::eof(); |
148 | } |
149 | |
150 | virtual int_type writeToDevice(char_type) |
151 | { |
152 | return char_traits::eof(); |
153 | } |
154 | |
155 | int_type _pb; |
156 | bool _ispb; |
157 | |
158 | BasicUnbufferedStreamBuf(const BasicUnbufferedStreamBuf&); |
159 | BasicUnbufferedStreamBuf& operator = (const BasicUnbufferedStreamBuf&); |
160 | }; |
161 | |
162 | |
163 | // |
164 | // We provide an instantiation for char. |
165 | // |
166 | // Visual C++ needs a workaround - explicitly importing the template |
167 | // instantiation - to avoid duplicate symbols due to multiple |
168 | // instantiations in different libraries. |
169 | // |
170 | #if defined(_MSC_VER) && defined(POCO_DLL) && !defined(Foundation_EXPORTS) |
171 | template class Foundation_API BasicUnbufferedStreamBuf<char, std::char_traits<char> >; |
172 | #endif |
173 | typedef BasicUnbufferedStreamBuf<char, std::char_traits<char> > UnbufferedStreamBuf; |
174 | |
175 | |
176 | } // namespace Poco |
177 | |
178 | |
179 | #endif // Foundation_UnbufferedStreamBuf_INCLUDED |
180 | |