Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qcstring.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** $Id: qcstring.cpp,v 1.2 2003/07/10 02:40:11 llornkcor Exp $
00003 **
00004 ** Implementation of extended char array operations, and QByteArray and
00005 ** QCString classes
00006 **
00007 ** Created : 920722
00008 **
00009 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
00010 **
00011 ** This file is part of the tools module of the Qt GUI Toolkit.
00012 **
00013 ** This file may be distributed under the terms of the Q Public License
00014 ** as defined by Trolltech AS of Norway and appearing in the file
00015 ** LICENSE.QPL included in the packaging of this file.
00016 **
00017 ** This file may be distributed and/or modified under the terms of the
00018 ** GNU General Public License version 2 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.GPL included in the
00020 ** packaging of this file.
00021 **
00022 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00023 ** licenses may use this file in accordance with the Qt Commercial License
00024 ** Agreement provided with the Software.
00025 **
00026 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00027 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00028 **
00029 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00030 **   information about Qt Commercial License Agreements.
00031 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00032 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00033 **
00034 ** Contact info@trolltech.com if any conditions of this licensing are
00035 ** not clear to you.
00036 **
00037 **********************************************************************/
00038 
00039 #include "qstring.h"
00040 #include "qregexp.h"
00041 #include "qdatastream.h"
00042 
00043 #ifdef QT_THREAD_SUPPORT
00044 #  include <private/qmutexpool_p.h>
00045 #endif // QT_THREAD_SUPPORT
00046 
00047 #include <stdio.h>
00048 #include <stdarg.h>
00049 #include <stdlib.h>
00050 #include <ctype.h>
00051 #include <limits.h>
00052 #ifndef QT_NO_COMPRESS
00053 #include "../3rdparty/zlib/zlib.h"
00054 #endif
00055 
00056 /*****************************************************************************
00057   Safe and portable C string functions; extensions to standard string.h
00058  *****************************************************************************/
00059 
00070 void *qmemmove( void *dst, const void *src, uint len )
00071 {
00072     register char *d;
00073     register char *s;
00074     if ( dst > src ) {
00075         d = (char *)dst + len - 1;
00076         s = (char *)src + len - 1;
00077         while ( len-- )
00078             *d-- = *s--;
00079     } else if ( dst < src ) {
00080         d = (char *)dst;
00081         s = (char *)src;
00082         while ( len-- )
00083             *d++ = *s++;
00084     }
00085     return dst;
00086 }
00087 
00088 
00100 char *qstrdup( const char *src )
00101 {
00102     if ( !src )
00103         return 0;
00104     char *dst = new char[strlen(src)+1];
00105     Q_CHECK_PTR( dst );
00106     return strcpy( dst, src );
00107 }
00108 
00133 char *qstrncpy( char *dst, const char *src, uint len )
00134 {
00135     if ( !src || !dst )
00136         return 0;
00137     strncpy( dst, src, len );
00138     if ( len > 0 )
00139         dst[len-1] = '\0';
00140     return dst;
00141 }
00142 
00216 int qstricmp( const char *str1, const char *str2 )
00217 {
00218     register const uchar *s1 = (const uchar *)str1;
00219     register const uchar *s2 = (const uchar *)str2;
00220     int res;
00221     uchar c;
00222     if ( !s1 || !s2 )
00223         return s1 ? 1 : ( s2 ? -1 : 0 );
00224     for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ )
00225         if ( !c )                               // strings are equal
00226             break;
00227     return res;
00228 }
00229 
00250 int qstrnicmp( const char *str1, const char *str2, uint len )
00251 {
00252     register const uchar *s1 = (const uchar *)str1;
00253     register const uchar *s2 = (const uchar *)str2;
00254     int res;
00255     uchar c;
00256     if ( !s1 || !s2 )
00257         return s1 ? 1 : ( s2 ? -1 : 0 );
00258     for ( ; len--; s1++, s2++ ) {
00259         if ( (res = (c=tolower(*s1)) - tolower(*s2)) )
00260             return res;
00261         if ( !c )                               // strings are equal
00262             break;
00263     }
00264     return 0;
00265 }
00266 
00267 
00268 static Q_UINT16 crc_tbl[16];
00269 static bool   crc_tbl_init = FALSE;
00270 
00271 static void createCRC16Table()                  // build CRC16 lookup table
00272 {
00273     register uint i;
00274     register uint j;
00275     uint v0, v1, v2, v3;
00276     for ( i = 0; i < 16; i++ ) {
00277         v0 = i & 1;
00278         v1 = ( i >> 1 ) & 1;
00279         v2 = ( i >> 2 ) & 1;
00280         v3 = ( i >> 3 ) & 1;
00281         j = 0;
00282 #undef SET_BIT
00283 #define SET_BIT(x, b, v) (x) |= (v) << (b)
00284         SET_BIT( j,  0, v0 );
00285         SET_BIT( j,  7, v0 );
00286         SET_BIT( j, 12, v0 );
00287         SET_BIT( j,  1, v1 );
00288         SET_BIT( j,  8, v1 );
00289         SET_BIT( j, 13, v1 );
00290         SET_BIT( j,  2, v2 );
00291         SET_BIT( j,  9, v2 );
00292         SET_BIT( j, 14, v2 );
00293         SET_BIT( j,  3, v3 );
00294         SET_BIT( j, 10, v3 );
00295         SET_BIT( j, 15, v3 );
00296         crc_tbl[i] = j;
00297     }
00298 }
00299 
00308 Q_UINT16 qChecksum( const char *data, uint len )
00309 {
00310     if ( !crc_tbl_init ) {                      // create lookup table
00311 
00312 #ifdef QT_THREAD_SUPPORT
00313         QMutexLocker locker( qt_global_mutexpool ?
00314                              qt_global_mutexpool->get( &crc_tbl_init ) : 0 );
00315 #endif // QT_THREAD_SUPPORT
00316 
00317         if ( !crc_tbl_init ) {
00318             createCRC16Table();
00319             crc_tbl_init = TRUE;
00320         }
00321     }
00322     register Q_UINT16 crc = 0xffff;
00323     uchar c;
00324     uchar *p = (uchar *)data;
00325     while ( len-- ) {
00326         c = *p++;
00327         crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)];
00328         c >>= 4;
00329         crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)];
00330     }
00331     return ~crc & 0xffff;
00332 }
00333 
00354 #ifndef QT_NO_COMPRESS
00355 QByteArray qCompress( const uchar* data, int nbytes )
00356 {
00357     if ( nbytes == 0 ) {
00358         QByteArray tmp( 4 );
00359         tmp.fill( 0 );
00360         return tmp;
00361     }
00362     if ( !data ) {
00363 #if defined(QT_CHECK_RANGE)
00364         qWarning( "qCompress: data is NULL." );
00365 #endif
00366         return QByteArray();
00367     }
00368 
00369     ulong len = nbytes * 2;
00370     QByteArray bazip;
00371     int res;
00372     do {
00373         bazip.resize( len + 4 );
00374         res = ::compress(  (uchar*)bazip.data()+4, &len, (uchar*)data, nbytes );
00375 
00376         switch ( res ) {
00377         case Z_OK:
00378             bazip.resize( len + 4 );
00379             bazip[0] = ( nbytes & 0xff000000 ) >> 24;
00380             bazip[1] = ( nbytes & 0x00ff0000 ) >> 16;
00381             bazip[2] = ( nbytes & 0x0000ff00 ) >> 8;
00382             bazip[3] = ( nbytes & 0x000000ff );
00383             break;
00384         case Z_MEM_ERROR:
00385 #if defined(QT_CHECK_RANGE)
00386             qWarning( "qCompress: Z_MEM_ERROR: Not enough memory." );
00387 #endif
00388             bazip.resize( 0 );
00389             break;
00390         case Z_BUF_ERROR:
00391             len *= 2;
00392             break;
00393         }
00394     } while ( res == Z_BUF_ERROR );
00395 
00396     return bazip;
00397 }
00398 #endif
00399 
00428 #ifndef QT_NO_COMPRESS
00429 QByteArray qUncompress( const uchar* data, int nbytes )
00430 {
00431     if ( !data ) {
00432 #if defined(QT_CHECK_RANGE)
00433         qWarning( "qUncompress: data is NULL." );
00434 #endif
00435         return QByteArray();
00436     }
00437     if ( nbytes <= 4 ) {
00438 #if defined(QT_CHECK_RANGE)
00439         if ( nbytes < 4 || ( data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0 ) )
00440             qWarning( "qUncompress: Input data is corrupted." );
00441 #endif
00442         return QByteArray();
00443     }
00444     ulong expectedSize = ( data[0] << 24 ) | ( data[1] << 16 ) | ( data[2] << 8 ) | data[3];
00445     ulong len = QMAX( expectedSize,  1 );
00446     QByteArray baunzip;
00447     int res;
00448     do {
00449         baunzip.resize( len );
00450         res = ::uncompress( (uchar*)baunzip.data(), &len,
00451                                 (uchar*)data+4, nbytes-4 );
00452 
00453         switch ( res ) {
00454         case Z_OK:
00455             if ( len != baunzip.size() )
00456                 baunzip.resize( len );
00457             break;
00458         case Z_MEM_ERROR:
00459 #if defined(QT_CHECK_RANGE)
00460             qWarning( "qUncompress: Z_MEM_ERROR: Not enough memory." );
00461 #endif
00462             break;
00463         case Z_BUF_ERROR:
00464             len *= 2;
00465             break;
00466         case Z_DATA_ERROR:
00467 #if defined(QT_CHECK_RANGE)
00468             qWarning( "qUncompress: Z_DATA_ERROR: Input data is corrupted." );
00469 #endif
00470             break;
00471         }
00472     } while ( res == Z_BUF_ERROR );
00473 
00474     if ( res != Z_OK )
00475         baunzip = QByteArray();
00476 
00477     return baunzip;
00478 }
00479 #endif
00480 
00481 /*****************************************************************************
00482   QByteArray documentation
00483  *****************************************************************************/
00484 
00511 /*****************************************************************************
00512   QByteArray stream functions
00513  *****************************************************************************/
00514 
00523 #ifndef QT_NO_DATASTREAM
00524 
00525 QDataStream &operator<<( QDataStream &s, const QByteArray &a )
00526 {
00527     return s.writeBytes( a.data(), a.size() );
00528 }
00529 
00539 QDataStream &operator>>( QDataStream &s, QByteArray &a )
00540 {
00541     Q_UINT32 len;
00542     s >> len;                                   // read size of array
00543     if ( len == 0 || s.eof() ) {                // end of file reached
00544         a.resize( 0 );
00545         return s;
00546     }
00547     if ( !a.resize( (uint)len ) ) {             // resize array
00548 #if defined(QT_CHECK_NULL)
00549         qWarning( "QDataStream: Not enough memory to read QByteArray" );
00550 #endif
00551         len = 0;
00552     }
00553     if ( len > 0 )                              // not null array
00554         s.readRawBytes( a.data(), (uint)len );
00555     return s;
00556 }
00557 
00558 #endif //QT_NO_DATASTREAM
00559 
00560 /*****************************************************************************
00561   QCString member functions
00562  *****************************************************************************/
00563 
00677 QCString::QCString( int size )
00678     : QByteArray( size )
00679 {
00680     if ( size > 0 ) {
00681         *data() = '\0';                         // set terminator
00682         *(data()+(size-1)) = '\0';
00683     }
00684 }
00685 
00694 QCString::QCString( const char *str )
00695 {
00696     duplicate( str, qstrlen(str) + 1 );
00697 }
00698 
00699 
00716 QCString::QCString( const char *str, uint maxsize )
00717 {
00718     if ( str == 0 )
00719         return;
00720     uint len; // index of first '\0'
00721     for ( len = 0; len < maxsize - 1; len++ ) {
00722         if ( str[len] == '\0' )
00723             break;
00724     }
00725     QByteArray::resize( len + 1 );
00726     memcpy( data(), str, len );
00727     data()[len] = 0;
00728 }
00729 
00734 QCString::~QCString()
00735 {
00736 }
00737 
00830 bool QCString::resize( uint len )
00831 {
00832     detach();
00833     uint wasNull = isNull();
00834     if ( !QByteArray::resize(len) )
00835         return FALSE;
00836     if ( len )
00837         data()[len - 1] = '\0';
00838     if ( len > 0 && wasNull )
00839         data()[0] = '\0';
00840     return TRUE;
00841 }
00842 
00843 
00872 QCString &QCString::sprintf( const char *format, ... )
00873 {
00874     detach();
00875     va_list ap;
00876     va_start( ap, format );
00877     if ( size() < 256 )
00878         QByteArray::resize( 256 );              // make string big enough
00879     vsprintf( data(), format, ap );
00880     resize( qstrlen(data()) + 1 );              // truncate
00881     va_end( ap );
00882     return *this;
00883 }
00884 
00885 
00896 bool QCString::fill( char c, int len )
00897 {
00898     detach();
00899     if ( len < 0 )
00900         len = length();
00901     if ( !QByteArray::fill(c,len+1) )
00902         return FALSE;
00903     *(data()+len) = '\0';
00904     return TRUE;
00905 }
00906 
00907 
00929 int QCString::find( char c, int index, bool cs ) const
00930 {
00931     if ( (uint)index >= size() )                // index outside string
00932         return -1;
00933     register const char *d;
00934     if ( cs ) {                                 // case sensitive
00935         d = strchr( data()+index, c );
00936     } else {
00937         d = data()+index;
00938         c = tolower( (uchar) c );
00939         while ( *d && tolower((uchar) *d) != c )
00940             d++;
00941         if ( !*d && c )                         // not found
00942             d = 0;
00943     }
00944     return d ? (int)(d - data()) : -1;
00945 }
00946 
00947 #define REHASH( a ) \
00948     if ( sl_minus_1 < sizeof(uint) * CHAR_BIT ) \
00949         hashHaystack -= (a) << sl_minus_1; \
00950     hashHaystack <<= 1
00951 
00967 int QCString::find( const char *str, int index, bool cs ) const
00968 {
00969     return find( str, index, cs, length() );
00970 }
00971 
00972 int QCString::find( const char *str, int index, bool cs, uint l ) const
00973 {
00974     if ( (uint)index >= size() )
00975         return -1;
00976     if ( !str )
00977         return -1;
00978     if ( !*str )
00979         return index;
00980     const uint sl = qstrlen( str );
00981     if ( sl + index > l )
00982         return -1;
00983 
00984     if ( sl == 1 )
00985         return find( *str, index, cs );
00986 
00987     /*
00988       See QString::find() for details.
00989     */
00990     const char* needle = str;
00991     const char* haystack = data() + index;
00992     const char* end = data() + (l-sl);
00993     const uint sl_minus_1 = sl-1;
00994     uint hashNeedle = 0, hashHaystack = 0,i;
00995 
00996     if ( cs ) {
00997         for ( i = 0; i < sl; ++i ) {
00998             hashNeedle = ((hashNeedle<<1) + needle[i] );
00999             hashHaystack = ((hashHaystack<<1) + haystack[i] );
01000         }
01001         hashHaystack -= *(haystack+sl_minus_1);
01002 
01003         while ( haystack <= end ) {
01004             hashHaystack += *(haystack+sl_minus_1);
01005             if ( hashHaystack == hashNeedle  && *needle == *haystack
01006                  && qstrncmp( needle, haystack, sl ) == 0 )
01007                 return haystack - data();
01008 
01009             REHASH( *haystack );
01010             ++haystack;
01011         }
01012     } else {
01013         for ( i = 0; i < sl; ++i ) {
01014             hashNeedle = ((hashNeedle<<1) +
01015                           tolower( needle[i] ) );
01016             hashHaystack = ((hashHaystack<<1) +
01017                             tolower( haystack[i] ) );
01018         }
01019         hashHaystack -= tolower(*(haystack+sl_minus_1));
01020 
01021         while ( haystack <= end ) {
01022             hashHaystack += tolower(*(haystack+sl_minus_1));
01023             if ( hashHaystack == hashNeedle
01024                  && qstrnicmp( needle, haystack, sl ) == 0 )
01025                 return haystack - data();
01026 
01027             REHASH( tolower(*haystack) );
01028             ++haystack;
01029         }
01030     }
01031     return -1;
01032 }
01033 
01034 
01047 int QCString::findRev( char c, int index, bool cs ) const
01048 {
01049     register const char *b = data();
01050     register const char *d;
01051     if ( index < 0 )
01052         index = length();
01053     if ( (uint)index >= size() )
01054         return -1;
01055     d = b + index;
01056     if ( cs ) {
01057         while ( d >= b && *d != c )
01058             d--;
01059     } else {
01060         c = tolower( (uchar) c );
01061         while ( d >= b && tolower((uchar) *d) != c )
01062             d--;
01063     }
01064     return d >= b ? (int)(d - b) : -1;
01065 }
01066 
01082 int QCString::findRev( const char *str, int index, bool cs ) const
01083 {
01084     /*
01085       See QString::find() for explanations.
01086     */
01087     const uint sl = qstrlen( str );
01088     const uint l = length();
01089     int delta = l-sl;
01090     if ( index < 0 )
01091         index = delta;
01092     if ( index < 0 || index > (int)l )
01093         return -1;
01094     if ( index > delta )
01095         index = delta;
01096 
01097     if ( sl == 1 )
01098         return findRev( *str, index, cs );
01099 
01100     const char* needle = str;
01101     const char* haystack = data() + index;
01102     const char* end = data();
01103     const uint sl_minus_1 = sl-1;
01104     const char* n = needle+sl_minus_1;
01105     const char* h = haystack+sl_minus_1;
01106     uint hashNeedle = 0, hashHaystack = 0, i;
01107 
01108     if ( cs ) {
01109         for ( i = 0; i < sl; ++i ) {
01110             hashNeedle = ((hashNeedle<<1) + *(n-i) );
01111             hashHaystack = ((hashHaystack<<1) + *(h-i) );
01112         }
01113         hashHaystack -= *haystack;
01114         while ( haystack >= end ) {
01115             hashHaystack += *haystack;
01116             if ( hashHaystack == hashNeedle  && qstrncmp( needle, haystack, sl ) == 0 )
01117                 return haystack-data();
01118             --haystack;
01119             REHASH( *(haystack+sl) );
01120         }
01121     } else {
01122         for ( i = 0; i < sl; ++i ) {
01123             hashNeedle = ((hashNeedle<<1) + tolower( *(n-i) ) );
01124             hashHaystack = ((hashHaystack<<1) + tolower( *(h-i) ) );
01125         }
01126         hashHaystack -= tolower(*haystack);
01127         while ( haystack >= end ) {
01128             hashHaystack += tolower(*haystack);
01129             if ( hashHaystack == hashNeedle && qstrnicmp( needle, haystack, sl ) == 0 )
01130                 return haystack-data();
01131             --haystack;
01132             REHASH( tolower(*(haystack+sl)) );
01133         }
01134     }
01135     return -1;
01136 }
01137 
01138 
01149 int QCString::contains( char c, bool cs ) const
01150 {
01151     int count = 0;
01152     char *d = data();
01153     if ( !d )
01154         return 0;
01155     if ( cs ) {                                 // case sensitive
01156         while ( *d )
01157             if ( *d++ == c )
01158                 count++;
01159     } else {                                    // case insensitive
01160         c = tolower( (uchar) c );
01161         while ( *d ) {
01162             if ( tolower((uchar) *d) == c )
01163                 count++;
01164             d++;
01165         }
01166     }
01167     return count;
01168 }
01169 
01185 int QCString::contains( const char *str, bool cs ) const
01186 {
01187     int count = 0;
01188     int i = -1;
01189     uint l = length();
01190     // use find for the faster hashing algorithm
01191     while ( ( i = find ( str, i+1, cs, l ) ) != -1 )
01192         count++;
01193     return count;
01194 }
01195 
01211 QCString QCString::left( uint len ) const
01212 {
01213     if ( isEmpty() ) {
01214         QCString empty;
01215         return empty;
01216     } else if ( len >= size() ) {
01217         QCString same( data() );
01218         return same;
01219     } else {
01220         QCString s( len+1 );
01221         strncpy( s.data(), data(), len );
01222         *(s.data()+len) = '\0';
01223         return s;
01224     }
01225 }
01226 
01243 QCString QCString::right( uint len ) const
01244 {
01245     if ( isEmpty() ) {
01246         QCString empty;
01247         return empty;
01248     } else {
01249         uint l = length();
01250         if ( len > l )
01251             len = l;
01252         char *p = data() + (l - len);
01253         return QCString( p );
01254     }
01255 }
01256 
01274 QCString QCString::mid( uint index, uint len ) const
01275 {
01276     uint slen = qstrlen( data() );
01277     if ( isEmpty() || index >= slen ) {
01278         QCString empty;
01279         return empty;
01280     } else {
01281         if ( len > slen-index )
01282             len = slen - index;
01283         register char *p = data()+index;
01284         QCString s( len+1 );
01285         strncpy( s.data(), p, len );
01286         *(s.data()+len) = '\0';
01287         return s;
01288     }
01289 }
01290 
01309 QCString QCString::leftJustify( uint width, char fill, bool truncate ) const
01310 {
01311     QCString result;
01312     int len = qstrlen(data());
01313     int padlen = width - len;
01314     if ( padlen > 0 ) {
01315         result.QByteArray::resize( len+padlen+1 );
01316         memcpy( result.data(), data(), len );
01317         memset( result.data()+len, fill, padlen );
01318         result[len+padlen] = '\0';
01319     } else {
01320         if ( truncate )
01321             result = left( width );
01322         else
01323             result = copy();
01324     }
01325     return result;
01326 }
01327 
01347 QCString QCString::rightJustify( uint width, char fill, bool truncate ) const
01348 {
01349     QCString result;
01350     int len = qstrlen(data());
01351     int padlen = width - len;
01352     if ( padlen > 0 ) {
01353         result.QByteArray::resize( len+padlen+1 );
01354         memset( result.data(), fill, padlen );
01355         memcpy( result.data()+padlen, data(), len );
01356         result[len+padlen] = '\0';
01357     } else {
01358         if ( truncate )
01359             result = left( width );
01360         else
01361             result = copy();
01362     }
01363     return result;
01364 }
01365 
01380 QCString QCString::lower() const
01381 {
01382     QCString s( data() );
01383     register char *p = s.data();
01384     if ( p ) {
01385         while ( *p ) {
01386             *p = tolower( (uchar) *p );
01387             p++;
01388         }
01389     }
01390     return s;
01391 }
01392 
01406 QCString QCString::upper() const
01407 {
01408     QCString s( data() );
01409     register char *p = s.data();
01410     if ( p ) {
01411         while ( *p ) {
01412             *p = toupper(*p);
01413             p++;
01414         }
01415     }
01416     return s;
01417 }
01418 
01419 
01436 QCString QCString::stripWhiteSpace() const
01437 {
01438     if ( isEmpty() )                            // nothing to do
01439         return copy();
01440 
01441     register char *s = data();
01442     QCString result = s;
01443     int reslen = result.length();
01444     if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) )
01445         return result;                          // returns a copy
01446 
01447     s = result.data();
01448     int start = 0;
01449     int end = reslen - 1;
01450     while ( isspace((uchar) s[start]) )         // skip white space from start
01451         start++;
01452     if ( s[start] == '\0' ) {                   // only white space
01453         result.resize( 1 );
01454         return result;
01455     }
01456     while ( end && isspace((uchar) s[end]) )    // skip white space from end
01457         end--;
01458     end -= start - 1;
01459     memmove( result.data(), &s[start], end );
01460     result.resize( end + 1 );
01461     return result;
01462 }
01463 
01464 
01481 QCString QCString::simplifyWhiteSpace() const
01482 {
01483     if ( isEmpty() )                            // nothing to do
01484         return copy();
01485     QCString result( size() );
01486     char *from  = data();
01487     char *to    = result.data();
01488     char *first = to;
01489     for ( ;; ) {
01490         while ( isspace((uchar) *from) )
01491             from++;
01492         while ( *from && !isspace((uchar) *from) )
01493             *to++ = *from++;
01494         if ( *from )
01495             *to++ = 0x20;                       // ' '
01496         else
01497             break;
01498     }
01499     if ( to > first && *(to-1) == 0x20 )
01500         to--;
01501     *to = '\0';
01502     result.resize( (int)(to - result.data()) + 1 );
01503     return result;
01504 }
01505 
01506 
01525 QCString &QCString::insert( uint index, const char *s )
01526 {
01527     int len = qstrlen(s);
01528     if ( len == 0 )
01529         return *this;
01530     uint olen = length();
01531     int nlen = olen + len;
01532     if ( index >= olen ) {                      // insert after end of string
01533         detach();
01534         if ( QByteArray::resize(nlen+index-olen+1, QByteArray::SpeedOptim ) ) {
01535             memset( data()+olen, ' ', index-olen );
01536             memcpy( data()+index, s, len+1 );
01537         }
01538     } else {
01539         detach();
01540         if ( QByteArray::resize(nlen+1, QByteArray::SpeedOptim ) ) {    // normal insert
01541             memmove( data()+index+len, data()+index, olen-index+1 );
01542             memcpy( data()+index, s, len );
01543         }
01544     }
01545     return *this;
01546 }
01547 
01565 QCString &QCString::insert( uint index, char c )        // insert char
01566 {
01567     char buf[2];
01568     buf[0] = c;
01569     buf[1] = '\0';
01570     return insert( index, buf );
01571 }
01572 
01597 QCString &QCString::remove( uint index, uint len )
01598 {
01599     uint olen = length();
01600     if ( index + len >= olen ) {                // range problems
01601         if ( index < olen ) {                   // index ok
01602             detach();
01603             resize( index+1 );
01604         }
01605     } else if ( len != 0 ) {
01606         detach();
01607         memmove( data()+index, data()+index+len, olen-index-len+1 );
01608         QByteArray::resize(olen-len+1, QByteArray::SpeedOptim );
01609     }
01610     return *this;
01611 }
01612 
01630 QCString &QCString::replace( uint index, uint len, const char *str )
01631 {
01632     remove( index, len );
01633     insert( index, str );
01634     return *this;
01635 }
01636 
01637 
01650 QCString &QCString::replace( char c, const char *after )
01651 {
01652     char str[2];
01653     str[0] = c;
01654     str[1] = '\0';
01655     return replace( str, after );
01656 }
01657 
01671 QCString &QCString::replace( const char *before, const char *after )
01672 {
01673     if ( before == after || isNull() )
01674         return *this;
01675 
01676     detach();
01677 
01678     int index = 0;
01679     const int bl = before ? strlen( before ) : 0;
01680     const int al = after ? strlen( after ) : 0;
01681     char *d = data();
01682     uint len = length();
01683 
01684     if ( bl == al ) {
01685         if ( bl ) {
01686             while( (index = find( before, index, TRUE, len ) ) != -1 ) {
01687                 memcpy( d+index, after, al );
01688                 index += bl;
01689             }
01690         }
01691     } else if ( al < bl ) {
01692         uint to = 0;
01693         uint movestart = 0;
01694         uint num = 0;
01695         while( (index = find( before, index, TRUE, len ) ) != -1 ) {
01696             if ( num ) {
01697                 int msize = index - movestart;
01698                 if ( msize > 0 ) {
01699                     memmove( d + to, d + movestart, msize );
01700                     to += msize;
01701                 }
01702             } else {
01703                 to = index;
01704             }
01705             if ( al ) {
01706                 memcpy( d + to, after, al );
01707                 to += al;
01708             }
01709             index += bl;
01710             movestart = index;
01711             num++;
01712         }
01713         if ( num ) {
01714             int msize = len - movestart;
01715             if ( msize > 0 )
01716                 memmove( d + to, d + movestart, msize );
01717             resize( len - num*(bl-al) + 1 );
01718         }
01719     } else {
01720         // the most complex case. We don't want to loose performance by doing repeated
01721         // copies and reallocs of the string.
01722         while( index != -1 ) {
01723             uint indices[4096];
01724             uint pos = 0;
01725             while( pos < 4095 ) {
01726                 index = find(before, index, TRUE, len);
01727                 if ( index == -1 )
01728                     break;
01729                 indices[pos++] = index;
01730                 index += bl;
01731                 // avoid infinite loop
01732                 if ( !bl )
01733                     index++;
01734             }
01735             if ( !pos )
01736                 break;
01737 
01738             // we have a table of replacement positions, use them for fast replacing
01739             int adjust = pos*(al-bl);
01740             // index has to be adjusted in case we get back into the loop above.
01741             if ( index != -1 )
01742                 index += adjust;
01743             uint newlen = len + adjust;
01744             int moveend = len;
01745             if ( newlen > len ) {
01746                 resize( newlen + 1 );
01747                 len = newlen;
01748             }
01749             d = data();
01750 
01751             while( pos ) {
01752                 pos--;
01753                 int movestart = indices[pos] + bl;
01754                 int insertstart = indices[pos] + pos*(al-bl);
01755                 int moveto = insertstart + al;
01756                 memmove( d + moveto, d + movestart, (moveend - movestart) );
01757                 if ( after )
01758                     memcpy( d + insertstart, after, al );
01759                 moveend = movestart - bl;
01760             }
01761         }
01762     }
01763     return *this;
01764 }
01765 
01771 QCString &QCString::replace( char c1, char c2 )
01772 {
01773     detach();
01774     uint i = 0;
01775     char *d = data();
01776     uint len = length();
01777     while ( i < len ) {
01778         if ( d[i] == c1 )
01779             d[i] = c2;
01780         i++;
01781     }
01782     return *this;
01783 }
01784 
01785 
01786 #ifndef QT_NO_REGEXP_CAPTURE
01787 
01801 int QCString::find( const QRegExp& rx, int index ) const
01802 {
01803     QString d = QString::fromAscii( data() );
01804     return d.find( rx, index );
01805 }
01806 
01821 int QCString::findRev( const QRegExp& rx, int index ) const
01822 {
01823     QString d = QString::fromAscii( data() );
01824     return d.findRev( rx, index );
01825 }
01826 
01846 int QCString::contains( const QRegExp &rx ) const
01847 {
01848     QString d = QString::fromAscii( data() );
01849     return d.contains( rx );
01850 }
01851 
01852 
01876 QCString &QCString::replace( const QRegExp &rx, const char *str )
01877 {
01878     QString d = QString::fromAscii( data() );
01879     QString r = QString::fromAscii( str );
01880     d.replace( rx, r );
01881     setStr( d.ascii() );
01882     return *this;
01883 }
01884 #endif //QT_NO_REGEXP
01885 
01894 long QCString::toLong( bool *ok ) const
01895 {
01896     char *p = data();
01897     long val=0;
01898     const long max_mult = 214748364;
01899     bool is_ok = FALSE;
01900     int neg = 0;
01901     if ( !p )
01902         goto bye;
01903     while ( isspace((uchar) *p) )               // skip leading space
01904         p++;
01905     if ( *p == '-' ) {
01906         p++;
01907         neg = 1;
01908     } else if ( *p == '+' ) {
01909         p++;
01910     }
01911     if ( !isdigit((uchar) *p) )
01912         goto bye;
01913     while ( isdigit((uchar) *p) ) {
01914         if ( val > max_mult || (val == max_mult && (*p-'0') > 7+neg) )
01915             goto bye;
01916         val = 10*val + (*p++ - '0');
01917     }
01918     if ( neg )
01919         val = -val;
01920     while ( isspace((uchar) *p) )               // skip trailing space
01921         p++;
01922     if ( *p == '\0' )
01923         is_ok = TRUE;
01924 bye:
01925     if ( ok )
01926         *ok = is_ok;
01927     return is_ok ? val : 0;
01928 }
01929 
01938 ulong QCString::toULong( bool *ok ) const
01939 {
01940     char *p = data();
01941     ulong val=0;
01942     const ulong max_mult = 429496729;
01943     bool is_ok = FALSE;
01944     if ( !p )
01945         goto bye;
01946     while ( isspace((uchar) *p) )               // skip leading space
01947         p++;
01948     if ( *p == '+' )
01949         p++;
01950     if ( !isdigit((uchar) *p) )
01951         goto bye;
01952     while ( isdigit((uchar) *p) ) {
01953         if ( val > max_mult || (val == max_mult && (*p-'0') > 5) )
01954             goto bye;
01955         val = 10*val + (*p++ - '0');
01956     }
01957     while ( isspace((uchar) *p) )               // skip trailing space
01958         p++;
01959     if ( *p == '\0' )
01960         is_ok = TRUE;
01961 bye:
01962     if ( ok )
01963         *ok = is_ok;
01964     return is_ok ? val : 0;
01965 }
01966 
01975 short QCString::toShort( bool *ok ) const
01976 {
01977     long v = toLong( ok );
01978     if ( ok && *ok && (v < -32768 || v > 32767) )
01979         *ok = FALSE;
01980     return (short)v;
01981 }
01982 
01991 ushort QCString::toUShort( bool *ok ) const
01992 {
01993     ulong v = toULong( ok );
01994     if ( ok && *ok && (v > 65535) )
01995         *ok = FALSE;
01996     return (ushort)v;
01997 }
01998 
01999 
02008 int QCString::toInt( bool *ok ) const
02009 {
02010     return (int)toLong( ok );
02011 }
02012 
02021 uint QCString::toUInt( bool *ok ) const
02022 {
02023     return (uint)toULong( ok );
02024 }
02025 
02034 double QCString::toDouble( bool *ok ) const
02035 {
02036     char *end;
02037     double val = strtod( data() ? data() : "", &end );
02038     if ( ok )
02039         *ok = ( data() && *data() && ( end == 0 || *end == '\0' ) );
02040     return val;
02041 }
02042 
02051 float QCString::toFloat( bool *ok ) const
02052 {
02053     return (float)toDouble( ok );
02054 }
02055 
02056 
02061 QCString &QCString::setStr( const char *str )
02062 {
02063     detach();
02064     if ( str )                                  // valid string
02065         store( str, qstrlen(str)+1 );
02066     else                                        // empty
02067         resize( 0 );
02068     return *this;
02069 }
02070 
02078 QCString &QCString::setNum( long n )
02079 {
02080     detach();
02081     char buf[20];
02082     register char *p = &buf[19];
02083     bool neg;
02084     if ( n < 0 ) {
02085         neg = TRUE;
02086         n = -n;
02087     } else {
02088         neg = FALSE;
02089     }
02090     *p = '\0';
02091     do {
02092         *--p = ((int)(n%10)) + '0';
02093         n /= 10;
02094     } while ( n );
02095     if ( neg )
02096         *--p = '-';
02097     store( p, qstrlen(p)+1 );
02098     return *this;
02099 }
02100 
02108 QCString &QCString::setNum( ulong n )
02109 {
02110     detach();
02111     char buf[20];
02112     register char *p = &buf[19];
02113     *p = '\0';
02114     do {
02115         *--p = ((int)(n%10)) + '0';
02116         n /= 10;
02117     } while ( n );
02118     store( p, qstrlen(p)+1 );
02119     return *this;
02120 }
02121 
02163 QCString &QCString::setNum( double n, char f, int prec )
02164 {
02165 #if defined(QT_CHECK_RANGE)
02166     if ( !(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G') )
02167         qWarning( "QCString::setNum: Invalid format char '%c'", f );
02168 #endif
02169     char format[20];
02170     register char *fs = format;                 // generate format string
02171     *fs++ = '%';                                //   "%.<prec>l<f>"
02172     if ( prec > 99 )
02173         prec = 99;
02174     *fs++ = '.';
02175     if ( prec >= 10 ) {
02176         *fs++ = prec / 10 + '0';
02177         *fs++ = prec % 10 + '0';
02178     } else {
02179         *fs++ = prec + '0';
02180     }
02181     *fs++ = 'l';
02182     *fs++ = f;
02183     *fs = '\0';
02184     return sprintf( format, n );
02185 }
02186 
02198 bool QCString::setExpand( uint index, char c )
02199 {
02200     detach();
02201     uint oldlen = length();
02202     if ( index >= oldlen ) {
02203         if ( !QByteArray::resize( index+2 ) )   // no memory
02204             return FALSE;
02205         if ( index > oldlen )
02206             memset( data() + oldlen, ' ', index - oldlen );
02207         *(data() + index+1) = '\0';             // terminate padded string
02208     }
02209     *(data() + index) = c;
02210     return TRUE;
02211 }
02212 
02213 
02232 QCString& QCString::operator+=( const char *str )
02233 {
02234     if ( !str )
02235         return *this;                           // nothing to append
02236     detach();
02237     uint len1 = length();
02238     uint len2 = qstrlen(str);
02239     if ( !QByteArray::resize( len1 + len2 + 1, QByteArray::SpeedOptim ) )
02240         return *this;                           // no memory
02241     memcpy( data() + len1, str, len2 + 1 );
02242     return *this;
02243 }
02244 
02251 QCString &QCString::operator+=( char c )
02252 {
02253     detach();
02254     uint len = length();
02255     if ( !QByteArray::resize( len + 2, QByteArray::SpeedOptim  ) )
02256         return *this;                           // no memory
02257     *(data() + len) = c;
02258     *(data() + len+1) = '\0';
02259     return *this;
02260 }
02261 
02262 
02263 /*****************************************************************************
02264   QCString stream functions
02265  *****************************************************************************/
02266 #ifndef QT_NO_DATASTREAM
02267 
02274 QDataStream &operator<<( QDataStream &s, const QCString &str )
02275 {
02276     return s.writeBytes( str.data(), str.size() );
02277 }
02278 
02287 QDataStream &operator>>( QDataStream &s, QCString &str )
02288 {
02289     str.detach();
02290     Q_UINT32 len;
02291     s >> len;                                   // read size of string
02292     if ( len == 0 || s.eof() ) {                // end of file reached
02293         str.resize( 0 );
02294         return s;
02295     }
02296     if ( !str.QByteArray::resize( (uint)len )) {// resize string
02297 #if defined(QT_CHECK_NULL)
02298         qWarning( "QDataStream: Not enough memory to read QCString" );
02299 #endif
02300         len = 0;
02301     }
02302     if ( len > 0 )                              // not null array
02303         s.readRawBytes( str.data(), (uint)len );
02304     return s;
02305 }
02306 #endif //QT_NO_DATASTREAM
02307 
02308 /*****************************************************************************
02309   Documentation for related functions
02310  *****************************************************************************/
02311 

Generated on Sat Nov 5 16:18:29 2005 for OPIE by  doxygen 1.4.2