1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
|
/*
* bytestream.cpp - base class for bytestreams
* Copyright (C) 2003 Justin Karneges
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <kdebug.h>
#include"bytestream.h"
// CS_NAMESPACE_BEGIN
//! \class ByteStream bytestream.h
//! \brief Base class for "bytestreams"
//!
//! This class provides a basic framework for a "bytestream", here defined
//! as a bi-directional, asynchronous pipe of data. It can be used to create
//! several different kinds of bytestream-applications, such as a console or
//! TCP connection, or something more abstract like a security layer or tunnel,
//! all with the same interface. The provided functions make creating such
//! classes simpler. ByteStream is a pure-virtual class, so you do not use it
//! on its own, but instead through a subclass such as \a BSocket.
//!
//! The signals connectionClosed(), delayedCloseFinished(), readyRead(),
//! bytesWritten(), and error() serve the exact same function as those from
//! <A HREF="http://doc.trolltech.com/3.1/qsocket.html">QSocket</A>.
//!
//! The simplest way to create a ByteStream is to reimplement isOpen(), close(),
//! and tryWrite(). Call appendRead() whenever you want to make data available for
//! reading. ByteStream will take care of the buffers with regards to the caller,
//! and will call tryWrite() when the write buffer gains data. It will be your
//! job to call tryWrite() whenever it is acceptable to write more data to
//! the underlying system.
//!
//! If you need more advanced control, reimplement read(), write(), bytesAvailable(),
//! and/or bytesToWrite() as necessary.
//!
//! Use appendRead(), appendWrite(), takeRead(), and takeWrite() to modify the
//! buffers. If you have more advanced requirements, the buffers can be accessed
//! directly with readBuf() and writeBuf().
//!
//! Also available are the static convenience functions ByteStream::appendArray()
//! and ByteStream::takeArray(), which make dealing with byte queues very easy.
class ByteStream::Private
{
public:
Private() {}
QByteArray readBuf, writeBuf;
};
//!
//! Constructs a ByteStream object with parent \a parent.
ByteStream::ByteStream(QObject *parent)
:QObject(parent)
{
// kdDebug(14181) << k_funcinfo << endl;
d = new Private;
}
//!
//! Destroys the object and frees allocated resources.
ByteStream::~ByteStream()
{
delete d;
}
//!
//! Returns TRUE if the stream is open, meaning that you can write to it.
bool ByteStream::isOpen() const
{
return false;
}
//!
//! Closes the stream. If there is data in the write buffer then it will be
//! written before actually closing the stream. Once all data has been written,
//! the delayedCloseFinished() signal will be emitted.
//! \sa delayedCloseFinished()
void ByteStream::close()
{
}
//!
//! Writes array \a a to the stream.
void ByteStream::write(const QByteArray &a)
{
// kdDebug(14181) << k_funcinfo << "[data size: " << a.size() << "]" << endl;
// kdDebug(14181) << k_funcinfo << "[Data: " << a << "]" << endl;
if(!isOpen())
return;
bool doWrite = bytesToWrite() == 0 ? true: false;
appendWrite(a);
if(doWrite)
tryWrite();
}
//!
//! Reads bytes \a bytes of data from the stream and returns them as an array. If \a bytes is 0, then
//! \a read will return all available data.
QByteArray ByteStream::read(int bytes)
{
// kdDebug(14181) << k_funcinfo << " " << bytes <<" [bytes]"<< endl;
return takeRead(bytes);
}
//!
//! Returns the number of bytes available for reading.
int ByteStream::bytesAvailable() const
{
return d->readBuf.size();
}
//!
//! Returns the number of bytes that are waiting to be written.
int ByteStream::bytesToWrite() const
{
// kdDebug(14181) << k_funcinfo << "[bytes left: " << d->writeBuf.size() << " ]" << endl;
return d->writeBuf.size();
}
//!
//! Writes string \a cs to the stream.
void ByteStream::write(const QCString &cs)
{
// kdDebug(14181) << k_funcinfo << "[data size: " << cs.length() << "]" << endl;
QByteArray block(cs.length());
memcpy(block.data(), cs.data(), block.size());
write(block);
}
//!
//! Clears the read buffer.
void ByteStream::clearReadBuffer()
{
d->readBuf.resize(0);
}
//!
//! Clears the write buffer.
void ByteStream::clearWriteBuffer()
{
d->writeBuf.resize(0);
}
//!
//! Appends \a block to the end of the read buffer.
void ByteStream::appendRead(const QByteArray &block)
{
// kdDebug(14181) << k_funcinfo << endl;
appendArray(&d->readBuf, block);
}
//!
//! Appends \a block to the end of the write buffer.
void ByteStream::appendWrite(const QByteArray &block)
{
// kdDebug(14181) << k_funcinfo << "[data size: " << block.size() << "]" << endl;
appendArray(&d->writeBuf, block);
}
//!
//! Returns \a size bytes from the start of the read buffer.
//! If \a size is 0, then all available data will be returned.
//! If \a del is TRUE, then the bytes are also removed.
QByteArray ByteStream::takeRead(int size, bool del)
{
// kdDebug(14181) << k_funcinfo << "[data size: " << size << "][ delete :" << del << " ]" << endl;
return takeArray(&d->readBuf, size, del);
}
//!
//! Returns \a size bytes from the start of the write buffer.
//! If \a size is 0, then all available data will be returned.
//! If \a del is TRUE, then the bytes are also removed.
QByteArray ByteStream::takeWrite(int size, bool del)
{
// kdDebug(14181) << k_funcinfo << "[data size: " << size << "][ delete :" << del << " ]" << endl;
return takeArray(&d->writeBuf, size, del);
}
//!
//! Returns a reference to the read buffer.
QByteArray & ByteStream::readBuf()
{
return d->readBuf;
}
//!
//! Returns a reference to the write buffer.
QByteArray & ByteStream::writeBuf()
{
// kdDebug(14181) << k_funcinfo << endl;
return d->writeBuf;
}
//!
//! Attempts to try and write some bytes from the write buffer, and returns the number
//! successfully written or -1 on error. The default implementation returns -1.
int ByteStream::tryWrite()
{
// kdDebug(14181) << k_funcinfo << "(THIS RETURNS -1)" << endl;
return -1;
}
//!
//! Append array \a b to the end of the array pointed to by \a a.
void ByteStream::appendArray(QByteArray *a, const QByteArray &b)
{
// kdDebug(14181) << k_funcinfo << endl;
int oldsize = a->size();
a->resize(oldsize + b.size());
memcpy(a->data() + oldsize, b.data(), b.size());
}
//!
//! Returns \a size bytes from the start of the array pointed to by \a from.
//! If \a size is 0, then all available data will be returned.
//! If \a del is TRUE, then the bytes are also removed.
QByteArray ByteStream::takeArray(QByteArray *from, int size, bool del)
{
// kdDebug(14181) << k_funcinfo << "[int size] : " << size << " [bool del] " << del << endl;
QByteArray a;
if(size == 0) {
a = from->copy();
if(del)
from->resize(0);
}
else {
if(size > (int)from->size())
size = from->size();
a.resize(size);
char *r = from->data();
memcpy(a.data(), r, size);
if(del) {
int newsize = from->size()-size;
memmove(r, r+size, newsize);
from->resize(newsize);
}
}
return a;
}
void connectionClosed();
void delayedCloseFinished();
void readyRead();
void bytesWritten(int);
void error(int);
//! \fn void ByteStream::connectionClosed()
//! This signal is emitted when the remote end of the stream closes.
//! \fn void ByteStream::delayedCloseFinished()
//! This signal is emitted when all pending data has been written to the stream
//! after an attempt to close.
//! \fn void ByteStream::readyRead()
//! This signal is emitted when data is available to be read.
//! \fn void ByteStream::bytesWritten(int x);
//! This signal is emitted when data has been successfully written to the stream.
//! \a x is the number of bytes written.
//! \fn void ByteStream::error(int code)
//! This signal is emitted when an error occurs in the stream. The reason for
//! error is indicated by \a code.
// CS_NAMESPACE_END
#include "bytestream.moc"
|