Orb/Doxygen/qtools/qbuffer.cpp
changeset 3 d8fccb2cd802
parent 0 42188c7ea2d9
equal deleted inserted replaced
2:932c358ece3e 3:d8fccb2cd802
       
     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 }