| 1 | // | 
|---|
| 2 | // MemoryStream.h | 
|---|
| 3 | // | 
|---|
| 4 | // Library: Foundation | 
|---|
| 5 | // Package: Streams | 
|---|
| 6 | // Module:  MemoryStream | 
|---|
| 7 | // | 
|---|
| 8 | // Definition of MemoryStreamBuf, MemoryInputStream, MemoryOutputStream | 
|---|
| 9 | // | 
|---|
| 10 | // Copyright (c) 2009, Applied Informatics Software Engineering GmbH. | 
|---|
| 11 | // and Contributors. | 
|---|
| 12 | // | 
|---|
| 13 | // SPDX-License-Identifier:	BSL-1.0 | 
|---|
| 14 | // | 
|---|
| 15 |  | 
|---|
| 16 |  | 
|---|
| 17 | #ifndef Foundation_MemoryStream_INCLUDED | 
|---|
| 18 | #define Foundation_MemoryStream_INCLUDED | 
|---|
| 19 |  | 
|---|
| 20 |  | 
|---|
| 21 | #include "Poco/Bugcheck.h" | 
|---|
| 22 | #include "Poco/Foundation.h" | 
|---|
| 23 | #include "Poco/StreamUtil.h" | 
|---|
| 24 | #include <streambuf> | 
|---|
| 25 | #include <iosfwd> | 
|---|
| 26 | #include <ios> | 
|---|
| 27 | #include <istream> | 
|---|
| 28 | #include <ostream> | 
|---|
| 29 |  | 
|---|
| 30 |  | 
|---|
| 31 | namespace Poco { | 
|---|
| 32 |  | 
|---|
| 33 |  | 
|---|
| 34 | template <typename ch, typename tr> | 
|---|
| 35 | class BasicMemoryStreamBuf: public std::basic_streambuf<ch, tr> | 
|---|
| 36 | /// BasicMemoryStreamBuf is a simple implementation of a | 
|---|
| 37 | /// stream buffer for reading and writing from a memory area. | 
|---|
| 38 | /// | 
|---|
| 39 | /// This streambuf only supports unidirectional streams. | 
|---|
| 40 | /// In other words, the BasicMemoryStreamBuf can be | 
|---|
| 41 | /// used for the implementation of an istream or an | 
|---|
| 42 | /// ostream, but not for an iostream. | 
|---|
| 43 | { | 
|---|
| 44 | protected: | 
|---|
| 45 | typedef std::basic_streambuf<ch, tr> Base; | 
|---|
| 46 | typedef std::basic_ios<ch, tr> IOS; | 
|---|
| 47 | typedef ch char_type; | 
|---|
| 48 | typedef tr char_traits; | 
|---|
| 49 | typedef typename Base::int_type int_type; | 
|---|
| 50 | typedef typename Base::pos_type pos_type; | 
|---|
| 51 | typedef typename Base::off_type off_type; | 
|---|
| 52 |  | 
|---|
| 53 | public: | 
|---|
| 54 | BasicMemoryStreamBuf(char_type* pBuffer, std::streamsize bufferSize): | 
|---|
| 55 | _pBuffer(pBuffer), | 
|---|
| 56 | _bufferSize(bufferSize) | 
|---|
| 57 | { | 
|---|
| 58 | this->setg(_pBuffer, _pBuffer, _pBuffer + _bufferSize); | 
|---|
| 59 | this->setp(_pBuffer, _pBuffer + _bufferSize); | 
|---|
| 60 | } | 
|---|
| 61 |  | 
|---|
| 62 | ~BasicMemoryStreamBuf() | 
|---|
| 63 | { | 
|---|
| 64 | } | 
|---|
| 65 |  | 
|---|
| 66 | virtual int_type overflow(int_type /*c*/) | 
|---|
| 67 | { | 
|---|
| 68 | return char_traits::eof(); | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | virtual int_type underflow() | 
|---|
| 72 | { | 
|---|
| 73 | return char_traits::eof(); | 
|---|
| 74 | } | 
|---|
| 75 |  | 
|---|
| 76 | virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) | 
|---|
| 77 | { | 
|---|
| 78 | const pos_type fail = off_type(-1); | 
|---|
| 79 | off_type newoff = off_type(-1); | 
|---|
| 80 |  | 
|---|
| 81 | if ((which & std::ios_base::in) != 0) | 
|---|
| 82 | { | 
|---|
| 83 | if (this->gptr() == 0) | 
|---|
| 84 | return fail; | 
|---|
| 85 |  | 
|---|
| 86 | if (way == std::ios_base::beg) | 
|---|
| 87 | { | 
|---|
| 88 | newoff = 0; | 
|---|
| 89 | } | 
|---|
| 90 | else if (way == std::ios_base::cur) | 
|---|
| 91 | { | 
|---|
| 92 | // cur is not valid if both in and out are specified (Condition 3) | 
|---|
| 93 | if ((which & std::ios_base::out) != 0) | 
|---|
| 94 | return fail; | 
|---|
| 95 | newoff = this->gptr() - this->eback(); | 
|---|
| 96 | } | 
|---|
| 97 | else if (way == std::ios_base::end) | 
|---|
| 98 | { | 
|---|
| 99 | newoff = this->egptr() - this->eback(); | 
|---|
| 100 | } | 
|---|
| 101 | else | 
|---|
| 102 | { | 
|---|
| 103 | poco_bugcheck(); | 
|---|
| 104 | } | 
|---|
| 105 |  | 
|---|
| 106 | if ((newoff + off) < 0 || (this->egptr() - this->eback()) < (newoff + off)) | 
|---|
| 107 | return fail; | 
|---|
| 108 | this->setg(this->eback(), this->eback() + newoff + off, this->egptr()); | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | if ((which & std::ios_base::out) != 0) | 
|---|
| 112 | { | 
|---|
| 113 | if (this->pptr() == 0) | 
|---|
| 114 | return fail; | 
|---|
| 115 |  | 
|---|
| 116 | if (way == std::ios_base::beg) | 
|---|
| 117 | { | 
|---|
| 118 | newoff = 0; | 
|---|
| 119 | } | 
|---|
| 120 | else if (way == std::ios_base::cur) | 
|---|
| 121 | { | 
|---|
| 122 | // cur is not valid if both in and out are specified (Condition 3) | 
|---|
| 123 | if ((which & std::ios_base::in) != 0) | 
|---|
| 124 | return fail; | 
|---|
| 125 | newoff = this->pptr() - this->pbase(); | 
|---|
| 126 | } | 
|---|
| 127 | else if (way == std::ios_base::end) | 
|---|
| 128 | { | 
|---|
| 129 | newoff = this->epptr() - this->pbase(); | 
|---|
| 130 | } | 
|---|
| 131 | else | 
|---|
| 132 | { | 
|---|
| 133 | poco_bugcheck(); | 
|---|
| 134 | } | 
|---|
| 135 |  | 
|---|
| 136 | if (newoff + off < 0 || (this->epptr() - this->pbase()) < newoff + off) | 
|---|
| 137 | return fail; | 
|---|
| 138 | this->pbump((int)(newoff + off - (this->pptr() - this->pbase()))); | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | return newoff; | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 | virtual int sync() | 
|---|
| 145 | { | 
|---|
| 146 | return 0; | 
|---|
| 147 | } | 
|---|
| 148 |  | 
|---|
| 149 | std::streamsize charsWritten() const | 
|---|
| 150 | { | 
|---|
| 151 | return static_cast<std::streamsize>(this->pptr() - this->pbase()); | 
|---|
| 152 | } | 
|---|
| 153 |  | 
|---|
| 154 | void reset() | 
|---|
| 155 | /// Resets the buffer so that current read and write positions | 
|---|
| 156 | /// will be set to the beginning of the buffer. | 
|---|
| 157 | { | 
|---|
| 158 | this->setg(_pBuffer, _pBuffer, _pBuffer + _bufferSize); | 
|---|
| 159 | this->setp(_pBuffer, _pBuffer + _bufferSize); | 
|---|
| 160 | } | 
|---|
| 161 |  | 
|---|
| 162 | private: | 
|---|
| 163 | char_type*      _pBuffer; | 
|---|
| 164 | std::streamsize _bufferSize; | 
|---|
| 165 |  | 
|---|
| 166 | BasicMemoryStreamBuf(); | 
|---|
| 167 | BasicMemoryStreamBuf(const BasicMemoryStreamBuf&); | 
|---|
| 168 | BasicMemoryStreamBuf& operator = (const BasicMemoryStreamBuf&); | 
|---|
| 169 | }; | 
|---|
| 170 |  | 
|---|
| 171 |  | 
|---|
| 172 | // | 
|---|
| 173 | // We provide an instantiation for char | 
|---|
| 174 | // | 
|---|
| 175 | typedef BasicMemoryStreamBuf<char, std::char_traits<char> > MemoryStreamBuf; | 
|---|
| 176 |  | 
|---|
| 177 |  | 
|---|
| 178 | class Foundation_API MemoryIOS: public virtual std::ios | 
|---|
| 179 | /// The base class for MemoryInputStream and MemoryOutputStream. | 
|---|
| 180 | /// | 
|---|
| 181 | /// This class is needed to ensure the correct initialization | 
|---|
| 182 | /// order of the stream buffer and base classes. | 
|---|
| 183 | { | 
|---|
| 184 | public: | 
|---|
| 185 | MemoryIOS(char* pBuffer, std::streamsize bufferSize); | 
|---|
| 186 | /// Creates the basic stream. | 
|---|
| 187 |  | 
|---|
| 188 | ~MemoryIOS(); | 
|---|
| 189 | /// Destroys the stream. | 
|---|
| 190 |  | 
|---|
| 191 | MemoryStreamBuf* rdbuf(); | 
|---|
| 192 | /// Returns a pointer to the underlying streambuf. | 
|---|
| 193 |  | 
|---|
| 194 | protected: | 
|---|
| 195 | MemoryStreamBuf _buf; | 
|---|
| 196 | }; | 
|---|
| 197 |  | 
|---|
| 198 |  | 
|---|
| 199 | class Foundation_API MemoryInputStream: public MemoryIOS, public std::istream | 
|---|
| 200 | /// An input stream for reading from a memory area. | 
|---|
| 201 | { | 
|---|
| 202 | public: | 
|---|
| 203 | MemoryInputStream(const char* pBuffer, std::streamsize bufferSize); | 
|---|
| 204 | /// Creates a MemoryInputStream for the given memory area, | 
|---|
| 205 | /// ready for reading. | 
|---|
| 206 |  | 
|---|
| 207 | ~MemoryInputStream(); | 
|---|
| 208 | /// Destroys the MemoryInputStream. | 
|---|
| 209 | }; | 
|---|
| 210 |  | 
|---|
| 211 |  | 
|---|
| 212 | class Foundation_API MemoryOutputStream: public MemoryIOS, public std::ostream | 
|---|
| 213 | /// An input stream for reading from a memory area. | 
|---|
| 214 | { | 
|---|
| 215 | public: | 
|---|
| 216 | MemoryOutputStream(char* pBuffer, std::streamsize bufferSize); | 
|---|
| 217 | /// Creates a MemoryOutputStream for the given memory area, | 
|---|
| 218 | /// ready for writing. | 
|---|
| 219 |  | 
|---|
| 220 | ~MemoryOutputStream(); | 
|---|
| 221 | /// Destroys the MemoryInputStream. | 
|---|
| 222 |  | 
|---|
| 223 | std::streamsize charsWritten() const; | 
|---|
| 224 | /// Returns the number of chars written to the buffer. | 
|---|
| 225 | }; | 
|---|
| 226 |  | 
|---|
| 227 |  | 
|---|
| 228 | // | 
|---|
| 229 | // inlines | 
|---|
| 230 | // | 
|---|
| 231 | inline MemoryStreamBuf* MemoryIOS::rdbuf() | 
|---|
| 232 | { | 
|---|
| 233 | return &_buf; | 
|---|
| 234 | } | 
|---|
| 235 |  | 
|---|
| 236 |  | 
|---|
| 237 | inline std::streamsize MemoryOutputStream::charsWritten() const | 
|---|
| 238 | { | 
|---|
| 239 | return _buf.charsWritten(); | 
|---|
| 240 | } | 
|---|
| 241 |  | 
|---|
| 242 |  | 
|---|
| 243 | } // namespace Poco | 
|---|
| 244 |  | 
|---|
| 245 |  | 
|---|
| 246 | #endif // Foundation_MemoryStream_INCLUDED | 
|---|
| 247 |  | 
|---|