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
28namespace Poco {
29
30
31template <typename ch, typename tr>
32class 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{
39protected:
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
49public:
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
138protected:
139 static int_type charToInt(char_type c)
140 {
141 return char_traits::to_int_type(c);
142 }
143
144private:
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)
171template class Foundation_API BasicUnbufferedStreamBuf<char, std::char_traits<char> >;
172#endif
173typedef BasicUnbufferedStreamBuf<char, std::char_traits<char> > UnbufferedStreamBuf;
174
175
176} // namespace Poco
177
178
179#endif // Foundation_UnbufferedStreamBuf_INCLUDED
180