Coverage Report

Created: 2024-01-11 06:12

/src/poco/Foundation/include/Poco/MemoryStream.h
Line
Count
Source (jump to first uncovered line)
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
0
  {
151
0
    return static_cast<std::streamsize>(this->pptr() - this->pbase());
152
0
  }
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
0
{
233
0
  return &_buf;
234
0
}
235
236
237
inline std::streamsize MemoryOutputStream::charsWritten() const
238
0
{
239
0
  return _buf.charsWritten();
240
0
}
241
242
243
} // namespace Poco
244
245
246
#endif // Foundation_MemoryStream_INCLUDED