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:
BasicUnbufferedStreamBuf()50 	BasicUnbufferedStreamBuf():
51 		_pb(char_traits::eof()),
52 		_ispb(false)
53 	{
54 		this->setg(0, 0, 0);
55 		this->setp(0, 0);
56 	}
57 
~BasicUnbufferedStreamBuf()58 	~BasicUnbufferedStreamBuf()
59 	{
60 	}
61 
overflow(int_type c)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 
underflow()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 
uflow()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 
pbackfail(int_type c)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 
xsgetn(char_type * p,std::streamsize count)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:
charToInt(char_type c)139 	static int_type charToInt(char_type c)
140 	{
141 		return char_traits::to_int_type(c);
142 	}
143 
144 private:
readFromDevice()145 	virtual int_type readFromDevice()
146 	{
147 		return char_traits::eof();
148 	}
149 
writeToDevice(char_type)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