Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
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 | ␊ |
83 | QBuffer::QBuffer()␊ |
84 | {␊ |
85 | setFlags( IO_Direct );␊ |
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 | ␊ |
114 | QBuffer::QBuffer( QByteArray buf ) : a(buf)␊ |
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 | ␊ |
128 | QBuffer::~QBuffer()␊ |
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 | ␊ |
145 | bool QBuffer::setBuffer( QByteArray buf )␊ |
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 | ␊ |
217 | void QBuffer::close()␊ |
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 | ␊ |
231 | void QBuffer::flush()␊ |
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() ) {␊ |
289 | ␉ setStatus( IO_ReadError );␊ |
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␊ |
334 | ␉ setStatus( IO_ResourceError );␊ |
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 | ␊ |
353 | int QBuffer::readLine( char *p, uint maxlen )␊ |
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 = d - a.data();␊ |
379 | return (uint)ioIndex - start;␊ |
380 | }␊ |
381 | ␊ |
382 | ␊ |
383 | /*!␊ |
384 | \reimp␊ |
385 | */␊ |
386 | ␊ |
387 | int QBuffer::getch()␊ |
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␊ |
400 | ␉setStatus( IO_ReadError );␊ |
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 | }␊ |
466 |