Coverage Report

Created: 2025-11-23 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poco/Foundation/include/Poco/MemoryStream.h
Line
Count
Source
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
  using Base = std::basic_streambuf<ch, tr>;
46
  using IOS = std::basic_ios<ch, tr>;
47
  using char_type = ch;
48
  using char_traits = tr;
49
  using int_type = typename Base::int_type;
50
  using pos_type = typename Base::pos_type;
51
  using off_type = typename Base::off_type;
52
53
public:
54
  BasicMemoryStreamBuf(char_type* pBuffer, std::streamsize bufferSize):
55
194k
    _pBuffer(pBuffer),
56
194k
    _bufferSize(bufferSize)
57
194k
  {
58
194k
    this->setg(_pBuffer, _pBuffer, _pBuffer + _bufferSize);
59
194k
    this->setp(_pBuffer, _pBuffer + _bufferSize);
60
194k
  }
61
62
  ~BasicMemoryStreamBuf() override = default;
63
64
  BasicMemoryStreamBuf() = delete;
65
  BasicMemoryStreamBuf(const BasicMemoryStreamBuf&) = delete;
66
  BasicMemoryStreamBuf& operator=(const BasicMemoryStreamBuf&) = delete;
67
68
  int_type overflow(int_type /*c*/) override
69
0
  {
70
0
    return char_traits::eof();
71
0
  }
72
73
  int_type underflow() override
74
350k
  {
75
350k
    return char_traits::eof();
76
350k
  }
77
78
  pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) override
79
0
  {
80
0
    const pos_type fail = off_type(-1);
81
0
    off_type newoff = off_type(-1);
82
83
0
    if ((which & std::ios_base::in) != 0)
84
0
    {
85
0
      if (this->gptr() == nullptr)
86
0
        return fail;
87
88
0
      if (way == std::ios_base::beg)
89
0
      {
90
0
        newoff = 0;
91
0
      }
92
0
      else if (way == std::ios_base::cur)
93
0
      {
94
        // cur is not valid if both in and out are specified (Condition 3)
95
0
        if ((which & std::ios_base::out) != 0)
96
0
          return fail;
97
0
        newoff = this->gptr() - this->eback();
98
0
      }
99
0
      else if (way == std::ios_base::end)
100
0
      {
101
0
        newoff = this->egptr() - this->eback();
102
0
      }
103
0
      else
104
0
      {
105
0
        poco_bugcheck();
106
0
      }
107
108
0
      if ((newoff + off) < 0 || (this->egptr() - this->eback()) < (newoff + off))
109
0
        return fail;
110
0
      this->setg(this->eback(), this->eback() + newoff + off, this->egptr());
111
0
    }
112
113
0
    if ((which & std::ios_base::out) != 0)
114
0
    {
115
0
      if (this->pptr() == nullptr)
116
0
        return fail;
117
118
0
      if (way == std::ios_base::beg)
119
0
      {
120
0
        newoff = 0;
121
0
      }
122
0
      else if (way == std::ios_base::cur)
123
0
      {
124
        // cur is not valid if both in and out are specified (Condition 3)
125
0
        if ((which & std::ios_base::in) != 0)
126
0
          return fail;
127
0
        newoff = this->pptr() - this->pbase();
128
0
      }
129
0
      else if (way == std::ios_base::end)
130
0
      {
131
0
        newoff = this->epptr() - this->pbase();
132
0
      }
133
0
      else
134
0
      {
135
0
        poco_bugcheck();
136
0
      }
137
138
0
      if (newoff + off < 0 || (this->epptr() - this->pbase()) < newoff + off)
139
0
        return fail;
140
0
      this->pbump((int)(newoff + off - (this->pptr() - this->pbase())));
141
0
    }
142
143
0
    return newoff;
144
0
  }
145
146
  pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) override
147
0
  {
148
0
    const off_type off = pos;
149
0
    return seekoff(off, std::ios::beg, which);
150
0
  }
151
152
  int sync() override
153
0
  {
154
0
    return 0;
155
0
  }
156
157
  std::streamsize charsWritten() const
158
0
  {
159
0
    return static_cast<std::streamsize>(this->pptr() - this->pbase());
160
0
  }
161
162
  void reset()
163
    /// Resets the buffer so that current read and write positions
164
    /// will be set to the beginning of the buffer.
165
  {
166
    this->setg(_pBuffer, _pBuffer, _pBuffer + _bufferSize);
167
    this->setp(_pBuffer, _pBuffer + _bufferSize);
168
  }
169
170
private:
171
  char_type*      _pBuffer;
172
  std::streamsize _bufferSize;
173
};
174
175
176
//
177
// We provide an instantiation for char
178
//
179
using MemoryStreamBuf = BasicMemoryStreamBuf<char, std::char_traits<char>>;
180
181
class Foundation_API MemoryIOS: public virtual std::ios
182
  /// The base class for MemoryInputStream and MemoryOutputStream.
183
  ///
184
  /// This class is needed to ensure the correct initialization
185
  /// order of the stream buffer and base classes.
186
{
187
public:
188
  MemoryIOS(char* pBuffer, std::streamsize bufferSize);
189
    /// Creates the basic stream.
190
191
  ~MemoryIOS() override;
192
  /// Destroys the stream.
193
194
  MemoryStreamBuf* rdbuf();
195
    /// Returns a pointer to the underlying streambuf.
196
197
protected:
198
  MemoryStreamBuf _buf;
199
};
200
201
202
class Foundation_API MemoryInputStream: public MemoryIOS, public std::istream
203
  /// An input stream for reading from a memory area.
204
{
205
public:
206
  MemoryInputStream(const char* pBuffer, std::streamsize bufferSize);
207
    /// Creates a MemoryInputStream for the given memory area,
208
    /// ready for reading.
209
210
  ~MemoryInputStream() override;
211
  /// Destroys the MemoryInputStream.
212
};
213
214
215
class Foundation_API MemoryOutputStream: public MemoryIOS, public std::ostream
216
  /// An input stream for reading from a memory area.
217
{
218
public:
219
  MemoryOutputStream(char* pBuffer, std::streamsize bufferSize);
220
    /// Creates a MemoryOutputStream for the given memory area,
221
    /// ready for writing.
222
223
  ~MemoryOutputStream() override;
224
  /// Destroys the MemoryInputStream.
225
226
  std::streamsize charsWritten() const;
227
    /// Returns the number of chars written to the buffer.
228
};
229
230
231
//
232
// inlines
233
//
234
inline MemoryStreamBuf* MemoryIOS::rdbuf()
235
0
{
236
0
  return &_buf;
237
0
}
238
239
240
inline std::streamsize MemoryOutputStream::charsWritten() const
241
0
{
242
0
  return _buf.charsWritten();
243
0
}
244
245
246
} // namespace Poco
247
248
249
#endif // Foundation_MemoryStream_INCLUDED