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