qbuffer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 **
4 ** Implementation of QBuffer class
5 **
6 ** Created : 930812
7 **
8 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9 **
10 ** This file is part of the tools module of the Qt GUI Toolkit.
11 **
12 ** This file may be distributed under the terms of the Q Public License
13 ** as defined by Trolltech AS of Norway and appearing in the file
14 ** LICENSE.QPL included in the packaging of this file.
15 **
16 ** This file may be distributed and/or modified under the terms of the
17 ** GNU General Public License version 2 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.GPL included in the
19 ** packaging of this file.
20 **
21 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22 ** licenses may use this file in accordance with the Qt Commercial License
23 ** Agreement provided with the Software.
24 **
25 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27 **
28 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29 ** information about Qt Commercial License Agreements.
30 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
31 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
32 **
33 ** Contact info@trolltech.com if any conditions of this licensing are
34 ** not clear to you.
35 **
36 **********************************************************************/
37 
38 #include "qbuffer.h"
39 #include <stdlib.h>
40 
41 // REVISED: paul
42 /*!
43  \class QBuffer qbuffer.h
44  \brief The QBuffer class is an I/O device that operates on a QByteArray
45 
46  \ingroup io
47 
48  QBuffer allows reading and writing a memory buffer. It is normally
49  used together with a QTextStream or a QDataStream. QBuffer has an
50  associated QByteArray which holds the buffer data. The size() of the
51  buffer is automatically adjusted as data is written.
52 
53  The constructor \c QBuffer(QByteArray) creates a QBuffer with an
54  existing byte array. The byte array can also be set with setBuffer().
55  Writing to the QBuffer will modify the original byte array, since
56  QByteArray is \link shclass.html explicitly shared.\endlink
57 
58  Use open() to open the buffer before use, and to set the mode
59  (read-only,write-only, etc.). close() closes the buffer. The buffer
60  must be closed before reopening or calling setBuffer().
61 
62  The common way to use QBuffer is through \l QDataStream or \l QTextStream
63  which have constructors that take a QBuffer parameter. For
64  convenience, there are also QDataStream and QTextStream constructors
65  that take a QByteArray parameter. These constructors create and open
66  an internal QBuffer.
67 
68  Note that QTextStream can also operate on a QString (a Unicode
69  string); a QBuffer cannot.
70 
71  You can also use QBuffer directly through the standard QIODevice
72  functions readBlock(), writeBlock() readLine(), at(), getch(), putch() and
73  ungetch().
74 
75  \sa QFile, QDataStream, QTextStream, QByteArray, \link shclass.html Shared Classes\endlink
76 */
77 
78 
79 /*!
80  Constructs an empty buffer.
81 */
82 
84 {
86  a_inc = 16; // initial increment
87  a_len = 0;
88  ioIndex = 0;
89 }
90 
91 
92 /*!
93  Constructs a buffer that operates on \a buf.
94  If you open the buffer in write mode (\c IO_WriteOnly or
95  \c IO_ReadWrite) and write something into the buffer, \a buf
96  will be modified.
97 
98 
99  Example:
100  \code
101  QCString str = "abc";
102  QBuffer b( str );
103  b.open( IO_WriteOnly );
104  b.at( 3 ); // position at \0
105  b.writeBlock( "def", 4 ); // write including \0
106  b.close();
107  // Now, str == "abcdef"
108  \endcode
109 
110 
111  \sa setBuffer()
112 */
113 
115 {
116  setFlags( IO_Direct );
117  a_len = a.size();
118  a_inc = (a_len > 512) ? 512 : a_len; // initial increment
119  if ( a_inc < 16 )
120  a_inc = 16;
121  ioIndex = 0;
122 }
123 
124 /*!
125  Destructs the buffer.
126 */
127 
129 {
130 }
131 
132 
133 /*!
134  Replaces the buffer's contents with \a buf.
135 
136  This may not be done when isOpen() is TRUE.
137 
138  Note that if you open the buffer in write mode (\c IO_WriteOnly or
139  IO_ReadWrite) and write something into the buffer, \a buf is also
140  modified because QByteArray is an explicitly shared class.
141 
142  \sa buffer(), open(), close()
143 */
144 
146 {
147  if ( isOpen() ) {
148 #if defined(CHECK_STATE)
149  qWarning( "QBuffer::setBuffer: Buffer is open");
150 #endif
151  return FALSE;
152  }
153  a = buf;
154  a_len = a.size();
155  a_inc = (a_len > 512) ? 512 : a_len; // initial increment
156  if ( a_inc < 16 )
157  a_inc = 16;
158  ioIndex = 0;
159  return TRUE;
160 }
161 
162 /*!
163  \fn QByteArray QBuffer::buffer() const
164 
165  Returns this buffer's byte array.
166 
167  \sa setBuffer()
168 */
169 
170 /*!
171  \reimp
172  Opens the buffer in the mode \a m. Returns TRUE if successful,
173  otherwise FALSE. The buffer must be opened before use.
174 
175  The mode parameter \a m must be a combination of the following flags.
176  <ul>
177  <li>\c IO_ReadOnly opens a buffer in read-only mode.
178  <li>\c IO_WriteOnly opens a buffer in write-only mode.
179  <li>\c IO_ReadWrite opens a buffer in read/write mode.
180  <li>\c IO_Append sets the buffer index to the end of the buffer.
181  <li>\c IO_Truncate truncates the buffer.
182  </ul>
183 
184  \sa close(), isOpen()
185 */
186 
187 bool QBuffer::open( int m )
188 {
189  if ( isOpen() ) { // buffer already open
190 #if defined(CHECK_STATE)
191  qWarning( "QBuffer::open: Buffer already open" );
192 #endif
193  return FALSE;
194  }
195  setMode( m );
196  if ( m & IO_Truncate ) { // truncate buffer
197  a.resize( 0 );
198  a_len = 0;
199  }
200  if ( m & IO_Append ) { // append to end of buffer
201  ioIndex = a.size();
202  } else {
203  ioIndex = 0;
204  }
205  a_inc = 16;
206  setState( IO_Open );
207  setStatus( 0 );
208  return TRUE;
209 }
210 
211 /*!
212  \reimp
213  Closes an open buffer.
214  \sa open()
215 */
216 
218 {
219  if ( isOpen() ) {
220  setFlags( IO_Direct );
221  ioIndex = 0;
222  a_inc = 16;
223  }
224 }
225 
226 /*!
227  \reimp
228  The flush function does nothing for a QBuffer.
229 */
230 
232 {
233  return;
234 }
235 
236 
237 /*!
238  \fn int QBuffer::at() const
239  \reimp
240 */
241 
242 /*!
243  \fn uint QBuffer::size() const
244  \reimp
245 */
246 
247 /*!
248  \reimp
249 */
250 
251 bool QBuffer::at( int pos )
252 {
253 #if defined(CHECK_STATE)
254  if ( !isOpen() ) {
255  qWarning( "QBuffer::at: Buffer is not open" );
256  return FALSE;
257  }
258 #endif
259  if ( (uint)pos > a_len ) {
260 #if defined(CHECK_RANGE)
261  qWarning( "QBuffer::at: Index %d out of range", pos );
262 #endif
263  return FALSE;
264  }
265  ioIndex = pos;
266  return TRUE;
267 }
268 
269 
270 /*!
271  \reimp
272 */
273 
274 int QBuffer::readBlock( char *p, uint len )
275 {
276 #if defined(CHECK_STATE)
277  CHECK_PTR( p );
278  if ( !isOpen() ) { // buffer not open
279  qWarning( "QBuffer::readBlock: Buffer not open" );
280  return -1;
281  }
282  if ( !isReadable() ) { // reading not permitted
283  qWarning( "QBuffer::readBlock: Read operation not permitted" );
284  return -1;
285  }
286 #endif
287  if ( (uint)ioIndex + len > a.size() ) { // overflow
288  if ( (uint)ioIndex >= a.size() ) {
290  return -1;
291  } else {
292  len = a.size() - (uint)ioIndex;
293  }
294  }
295  memcpy( p, a.data()+ioIndex, len );
296  ioIndex += len;
297  return len;
298 }
299 
300 /*!
301  \reimp
302 
303  Writes \a len bytes from \a p into the buffer at the current index,
304  overwriting any characters there and extending the buffer if necessary.
305  Returns the number of bytes actually written.
306 
307  Returns -1 if a serious error occurred.
308 
309  \sa readBlock()
310 */
311 
312 int QBuffer::writeBlock( const char *p, uint len )
313 {
314 #if defined(CHECK_NULL)
315  if ( p == 0 && len != 0 )
316  qWarning( "QBuffer::writeBlock: Null pointer error" );
317 #endif
318 #if defined(CHECK_STATE)
319  if ( !isOpen() ) { // buffer not open
320  qWarning( "QBuffer::writeBlock: Buffer not open" );
321  return -1;
322  }
323  if ( !isWritable() ) { // writing not permitted
324  qWarning( "QBuffer::writeBlock: Write operation not permitted" );
325  return -1;
326  }
327 #endif
328  if ( (uint)ioIndex + len >= a_len ) { // overflow
329  uint new_len = a_len + a_inc*(((uint)ioIndex+len-a_len)/a_inc+1);
330  if ( !a.resize( new_len ) ) { // could not resize
331 #if defined(CHECK_NULL)
332  qWarning( "QBuffer::writeBlock: Memory allocation error" );
333 #endif
335  return -1;
336  }
337  a_inc *= 2; // double increment
338  a_len = new_len;
339  a.shd->len = (uint)ioIndex + len;
340  }
341  memcpy( a.data()+ioIndex, p, len );
342  ioIndex += len;
343  if ( a.shd->len < (uint)ioIndex )
344  a.shd->len = (uint)ioIndex; // fake (not alloc'd) length
345  return len;
346 }
347 
348 
349 /*!
350  \reimp
351 */
352 
354 {
355 #if defined(CHECK_STATE)
356  CHECK_PTR( p );
357  if ( !isOpen() ) { // buffer not open
358  qWarning( "QBuffer::readLine: Buffer not open" );
359  return -1;
360  }
361  if ( !isReadable() ) { // reading not permitted
362  qWarning( "QBuffer::readLine: Read operation not permitted" );
363  return -1;
364  }
365 #endif
366  if ( maxlen == 0 )
367  return 0;
368  uint start = (uint)ioIndex;
369  char *d = a.data() + ioIndex;
370  maxlen--; // make room for 0-terminator
371  if ( a.size() - (uint)ioIndex < maxlen )
372  maxlen = a.size() - (uint)ioIndex;
373  while ( maxlen-- ) {
374  if ( (*p++ = *d++) == '\n' )
375  break;
376  }
377  *p = '\0';
378  ioIndex = (int)(d - a.data());
379  return (uint)ioIndex - start;
380 }
381 
382 
383 /*!
384  \reimp
385 */
386 
388 {
389 #if defined(CHECK_STATE)
390  if ( !isOpen() ) { // buffer not open
391  qWarning( "QBuffer::getch: Buffer not open" );
392  return -1;
393  }
394  if ( !isReadable() ) { // reading not permitted
395  qWarning( "QBuffer::getch: Read operation not permitted" );
396  return -1;
397  }
398 #endif
399  if ( (uint)ioIndex+1 > a.size() ) { // overflow
401  return -1;
402  }
403  return uchar(*(a.data()+ioIndex++));
404 }
405 
406 /*!
407  \reimp
408  Writes the character \a ch into the buffer, overwriting
409  the character at the current index, extending the buffer
410  if necessary.
411 
412  Returns \a ch, or -1 if some error occurred.
413 
414  \sa getch(), ungetch()
415 */
416 
417 int QBuffer::putch( int ch )
418 {
419 #if defined(CHECK_STATE)
420  if ( !isOpen() ) { // buffer not open
421  qWarning( "QBuffer::putch: Buffer not open" );
422  return -1;
423  }
424  if ( !isWritable() ) { // writing not permitted
425  qWarning( "QBuffer::putch: Write operation not permitted" );
426  return -1;
427  }
428 #endif
429  if ( (uint)ioIndex + 1 >= a_len ) { // overflow
430  char buf[1];
431  buf[0] = (char)ch;
432  if ( writeBlock(buf,1) != 1 )
433  return -1; // write error
434  } else {
435  *(a.data() + ioIndex++) = (char)ch;
436  if ( a.shd->len < (uint)ioIndex )
437  a.shd->len = (uint)ioIndex;
438  }
439  return ch;
440 }
441 
442 /*!
443  \reimp
444 */
445 
446 int QBuffer::ungetch( int ch )
447 {
448 #if defined(CHECK_STATE)
449  if ( !isOpen() ) { // buffer not open
450  qWarning( "QBuffer::ungetch: Buffer not open" );
451  return -1;
452  }
453  if ( !isReadable() ) { // reading not permitted
454  qWarning( "QBuffer::ungetch: Read operation not permitted" );
455  return -1;
456  }
457 #endif
458  if ( ch != -1 ) {
459  if ( ioIndex )
460  ioIndex--;
461  else
462  ch = -1;
463  }
464  return ch;
465 }
int putch(int)
Definition: qbuffer.cpp:417
bool setBuffer(QByteArray)
Definition: qbuffer.cpp:145
static const int maxlen
Definition: qregexp.cpp:904
bool resize(uint size)
Definition: qarray.h:69
void close()
Definition: qbuffer.cpp:217
int readBlock(char *p, uint)
Definition: qbuffer.cpp:274
void setFlags(int f)
Definition: qiodevice.h:136
#define IO_ReadError
Definition: qiodevice.h:78
const bool FALSE
Definition: qglobal.h:370
int getch()
Definition: qbuffer.cpp:387
void qWarning(const char *msg,...)
Definition: qglobal.cpp:409
void setMode(int)
Definition: qiodevice.cpp:378
void flush()
Definition: qbuffer.cpp:231
void setStatus(int)
Definition: qiodevice.cpp:408
int writeBlock(const char *p, uint)
Definition: qbuffer.cpp:312
bool isReadable() const
Definition: qiodevice.h:106
unsigned char uchar
Definition: nybbler.cc:11
#define IO_Direct
Definition: qiodevice.h:49
int at() const
Definition: qbuffer.h:94
type * data() const
Definition: qarray.h:63
bool open(int)
Definition: qbuffer.cpp:187
#define IO_Truncate
Definition: qiodevice.h:65
#define IO_ResourceError
Definition: qiodevice.h:81
bool isWritable() const
Definition: qiodevice.h:107
~QBuffer()
Definition: qbuffer.cpp:128
p
Definition: test.py:223
#define IO_Append
Definition: qiodevice.h:64
void setState(int)
Definition: qiodevice.cpp:393
int ungetch(int)
Definition: qbuffer.cpp:446
uint a_len
Definition: qbuffer.h:77
#define CHECK_PTR(p)
Definition: qglobal.h:601
QByteArray a
Definition: qbuffer.h:74
QBuffer()
Definition: qbuffer.cpp:83
bool isOpen() const
Definition: qiodevice.h:110
uint size() const
Definition: qarray.h:65
unsigned uint
Definition: qglobal.h:351
#define IO_Open
Definition: qiodevice.h:71
const bool TRUE
Definition: qglobal.h:371
uint a_inc
Definition: qbuffer.h:78
int readLine(char *p, uint)
Definition: qbuffer.cpp:353
int ioIndex
Definition: qiodevice.h:141