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
31namespace Poco {
32
33
34template <typename ch, typename tr>
35class 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{
44protected:
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
53public:
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
162private:
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//
175typedef BasicMemoryStreamBuf<char, std::char_traits<char> > MemoryStreamBuf;
176
177
178class 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{
184public:
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
194protected:
195 MemoryStreamBuf _buf;
196};
197
198
199class Foundation_API MemoryInputStream: public MemoryIOS, public std::istream
200 /// An input stream for reading from a memory area.
201{
202public:
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
212class Foundation_API MemoryOutputStream: public MemoryIOS, public std::ostream
213 /// An input stream for reading from a memory area.
214{
215public:
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//
231inline MemoryStreamBuf* MemoryIOS::rdbuf()
232{
233 return &_buf;
234}
235
236
237inline std::streamsize MemoryOutputStream::charsWritten() const
238{
239 return _buf.charsWritten();
240}
241
242
243} // namespace Poco
244
245
246#endif // Foundation_MemoryStream_INCLUDED
247