Coverage Report

Created: 2025-06-13 06:07

/src/poco/Foundation/include/Poco/BufferedBidirectionalStreamBuf.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// BufferedBidirectionalStreamBuf.h
3
//
4
// Library: Foundation
5
// Package: Streams
6
// Module:  StreamBuf
7
//
8
// Definition of template BasicBufferedBidirectionalStreamBuf and class BufferedBidirectionalStreamBuf.
9
//
10
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
11
// and Contributors.
12
//
13
// SPDX-License-Identifier: BSL-1.0
14
//
15
16
17
#ifndef Foundation_BufferedBidirectionalStreamBuf_INCLUDED
18
#define Foundation_BufferedBidirectionalStreamBuf_INCLUDED
19
20
21
#include "Poco/Foundation.h"
22
#include "Poco/BufferAllocator.h"
23
#include "Poco/StreamUtil.h"
24
#include <streambuf>
25
#include <iosfwd>
26
#include <ios>
27
28
29
namespace Poco {
30
31
32
template <typename ch, typename tr, typename ba = BufferAllocator<ch>>
33
class BasicBufferedBidirectionalStreamBuf: public std::basic_streambuf<ch, tr>
34
  /// This is an implementation of a buffered bidirectional
35
  /// streambuf that greatly simplifies the implementation of
36
  /// custom streambufs of various kinds.
37
  /// Derived classes only have to override the methods
38
  /// readFromDevice() or writeToDevice().
39
  ///
40
  /// In contrast to BasicBufferedStreambuf, this class supports
41
  /// simultaneous read and write access, so in addition to
42
  /// istream and ostream this streambuf can also be used
43
  /// for implementing an iostream.
44
{
45
protected:
46
  using Base = std::basic_streambuf<ch, tr>;
47
  using IOS = std::basic_ios<ch, tr>;
48
  using char_type = ch;
49
  using char_traits = tr;
50
  using Allocator = ba;
51
  using int_type = typename Base::int_type;
52
  using pos_type = typename Base::pos_type;
53
  using off_type = typename Base::off_type;
54
  using openmode = typename IOS::openmode;
55
56
public:
57
  BasicBufferedBidirectionalStreamBuf(std::streamsize bufferSize, openmode mode):
58
56.7k
    _bufsize(bufferSize),
59
56.7k
    _pReadBuffer(Allocator::allocate(_bufsize)),
60
56.7k
    _pWriteBuffer(Allocator::allocate(_bufsize)),
61
56.7k
    _mode(mode)
62
56.7k
  {
63
56.7k
    resetBuffers();
64
56.7k
  }
65
66
  ~BasicBufferedBidirectionalStreamBuf() override
67
56.7k
  {
68
56.7k
    Allocator::deallocate(_pReadBuffer, _bufsize);
69
56.7k
    Allocator::deallocate(_pWriteBuffer, _bufsize);
70
56.7k
  }
71
72
  BasicBufferedBidirectionalStreamBuf(const BasicBufferedBidirectionalStreamBuf&) = delete;
73
  BasicBufferedBidirectionalStreamBuf& operator = (const BasicBufferedBidirectionalStreamBuf&) = delete;
74
75
  int_type overflow(int_type c) override
76
0
  {
77
0
    if (!(_mode & IOS::out)) return char_traits::eof();
78
79
0
    if (flushBuffer() == std::streamsize(-1)) return char_traits::eof();
80
0
    if (c != char_traits::eof())
81
0
    {
82
0
      *this->pptr() = char_traits::to_char_type(c);
83
0
      this->pbump(1);
84
0
    }
85
86
0
    return c;
87
0
  }
88
89
  int_type underflow() override
90
56.7k
  {
91
56.7k
    if (!(_mode & IOS::in)) return char_traits::eof();
92
93
56.7k
    if (this->gptr() && (this->gptr() < this->egptr()))
94
0
      return char_traits::to_int_type(*this->gptr());
95
96
56.7k
    int putback = int(this->gptr() - this->eback());
97
56.7k
    if (putback > 4) putback = 4;
98
99
56.7k
    char_traits::move(_pReadBuffer + (4 - putback), this->gptr() - putback, putback);
100
101
56.7k
    int n = readFromDevice(_pReadBuffer + 4, _bufsize - 4);
102
56.7k
    if (n <= 0) return char_traits::eof();
103
104
56.7k
    this->setg(_pReadBuffer + (4 - putback), _pReadBuffer + 4, _pReadBuffer + 4 + n);
105
106
    // return next character
107
56.7k
    return char_traits::to_int_type(*this->gptr());
108
56.7k
  }
109
110
  int sync() override
111
56.7k
  {
112
56.7k
    if (this->pptr() && this->pptr() > this->pbase())
113
0
    {
114
0
      if (flushBuffer() == -1) return -1;
115
0
    }
116
56.7k
    return 0;
117
56.7k
  }
118
119
protected:
120
  void setMode(openmode mode)
121
56.7k
  {
122
56.7k
    _mode = mode;
123
56.7k
  }
124
125
  openmode getMode() const
126
56.7k
  {
127
56.7k
    return _mode;
128
56.7k
  }
129
130
  void resetBuffers()
131
113k
  {
132
113k
    this->setg(_pReadBuffer + 4, _pReadBuffer + 4, _pReadBuffer + 4);
133
113k
    this->setp(_pWriteBuffer, _pWriteBuffer + _bufsize);
134
113k
  }
135
136
  virtual bool resizeBuffer(std::streamsize bufferSize)
137
0
  {
138
0
    if (_bufsize != bufferSize)
139
0
    {
140
0
      Allocator::deallocate(_pReadBuffer, _bufsize);
141
0
      Allocator::deallocate(_pWriteBuffer, _bufsize);
142
143
0
      _bufsize = bufferSize;
144
0
      _pReadBuffer = Allocator::allocate(_bufsize);
145
0
      _pWriteBuffer = Allocator::allocate(_bufsize);
146
0
    }
147
0
    resetBuffers();
148
149
0
    return true;
150
0
  }
151
152
private:
153
  virtual int readFromDevice(char_type* /*buffer*/, std::streamsize /*length*/)
154
0
  {
155
0
    return 0;
156
0
  }
157
158
  virtual int writeToDevice(const char_type* /*buffer*/, std::streamsize /*length*/)
159
0
  {
160
0
    return 0;
161
0
  }
162
163
  int flushBuffer()
164
0
  {
165
0
    int n = int(this->pptr() - this->pbase());
166
0
    if (writeToDevice(this->pbase(), n) == n)
167
0
    {
168
0
      this->pbump(-n);
169
0
      return n;
170
0
    }
171
0
    return -1;
172
0
  }
173
174
  std::streamsize _bufsize {0};
175
  char_type*      _pReadBuffer {nullptr};
176
  char_type*      _pWriteBuffer {nullptr};
177
  openmode        _mode {0};
178
};
179
180
181
//
182
// We provide an instantiation for char.
183
//
184
185
#if defined(POCO_OS_FAMILY_WINDOWS)
186
extern template class BasicBufferedBidirectionalStreamBuf<char, std::char_traits<char>>;
187
#else
188
extern template class Foundation_API BasicBufferedBidirectionalStreamBuf<char, std::char_traits<char>>;
189
#endif
190
191
using BufferedBidirectionalStreamBuf = BasicBufferedBidirectionalStreamBuf<char, std::char_traits<char>>;
192
193
} // namespace Poco
194
195
196
#endif // Foundation_BufferedBidirectionalStreamBuf_INCLUDED