summaryrefslogtreecommitdiffstats
path: root/qtools
diff options
context:
space:
mode:
Diffstat (limited to 'qtools')
-rw-r--r--qtools/qcstring.cpp620
-rw-r--r--qtools/qcstring.h786
-rw-r--r--qtools/qtools.pro.in3
-rw-r--r--qtools/scstring.cpp798
-rw-r--r--qtools/scstring.h155
5 files changed, 1583 insertions, 779 deletions
diff --git a/qtools/qcstring.cpp b/qtools/qcstring.cpp
index 7bf6f50..4038d55 100644
--- a/qtools/qcstring.cpp
+++ b/qtools/qcstring.cpp
@@ -3,8 +3,8 @@
* Copyright (C) 1997-2004 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
- * documentation under the terms of the GNU General Public License is hereby
- * granted. No representations are made about the suitability of this software
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
@@ -24,148 +24,281 @@
#include <qregexp.h>
#include <qdatastream.h>
-QCString &QCString::sprintf( const char *format, ... )
+
+QCString::QCString(int size)
{
- va_list ap;
- va_start( ap, format );
- const int minlen=256;
- if (length()<minlen) resize(minlen);
- vsnprintf( data(), minlen, format, ap);
- resize(strlen(data())+1);
- va_end( ap );
+ if (size>0)
+ {
+ m_data = (char *)malloc(size);
+ if (m_data)
+ {
+ if (size>1) memset(m_data,' ',size-1);
+ m_data[size-1]='\0';
+ }
+ }
+ else
+ {
+ m_data=0;
+ }
+}
+
+QCString::QCString( const QCString &s )
+{
+ duplicate(s);
+}
+
+QCString::QCString( const char *str )
+{
+ duplicate(str);
+}
+
+QCString::QCString( const char *str, uint maxlen )
+{
+ uint l;
+ if (str && ( l = QMIN(qstrlen(str),maxlen) ))
+ {
+ m_data=(char *)malloc(l+1);
+ strncpy(m_data,str,l+1);
+ m_data[l]='\0';
+ }
+ else
+ {
+ m_data=0;
+ }
+}
+
+QCString::~QCString()
+{
+ if (m_data) free(m_data);
+ m_data=0;
+}
+
+QCString &QCString::assign( const char *str )
+{
+ if (m_data) free(m_data);
+ duplicate(str);
return *this;
}
-int QCString::find( char c, int index, bool cs ) const
+bool QCString::resize( uint newlen )
{
- if (index<0 || index>=(int)length()) return -1; // index outside string
- register const char *pos;
- if (cs)
+ if (newlen==0)
+ {
+ if (m_data) { free(m_data); m_data=0; }
+ return TRUE;
+ }
+ if (m_data==0) // newlen>0
{
- pos = strchr(data()+index,c);
+ m_data = (char *)malloc(newlen);
}
else
{
- pos = data()+index;
- c = tolower((unsigned char)c);
- while (*pos && tolower((unsigned char)*pos)!=c) pos++;
- if (!*pos && c) pos=0; // not found
+ m_data = (char *)realloc(m_data,newlen);
}
- return pos ? (int)(pos - data()) : -1;
+ if (m_data==0) return FALSE;
+ m_data[newlen-1]='\0';
+ return TRUE;
}
-int QCString::find( const char *str, int index, bool cs ) const
+bool QCString::fill( char c, int len )
{
- int l = length();
- if (index<0 || index>=l) return -1; // index outside string
- if (!str) return -1; // no string to search for
- if (!*str) return index; // empty string matching at index
- register char *pos;
- if (cs) // case sensitive
+ uint l=length();
+ if (len<0) len=l;
+ if ((uint)len!=l)
{
- pos = strstr(data()+index,str);
+ if (m_data) free(m_data);
+ if (len>0)
+ {
+ m_data=(char *)malloc(len+1);
+ if (m_data==0) return FALSE;
+ m_data[len]='\0';
+ }
+ else
+ {
+ m_data=0;
+ }
}
- else // case insensitive
+ if (len>0)
{
- pos = data();
- int len = strlen(str);
- while (*pos)
+ uint i;
+ for (i=0;i<(uint)len;i++) m_data[i]=c;
+ }
+ return TRUE;
+}
+
+QCString &QCString::sprintf( const char *format, ... )
+{
+ va_list ap;
+ va_start( ap, format );
+ uint l = length();
+ const uint minlen=256;
+ if (l<minlen)
+ {
+ if (m_data)
+ m_data = (char *)realloc(m_data,minlen);
+ else
+ m_data = (char *)malloc(minlen);
+ }
+ vsprintf( m_data, format, ap );
+ resize( qstrlen(m_data) + 1 ); // truncate
+ va_end( ap );
+ return *this;
+}
+
+
+int QCString::find( char c, int index, bool cs ) const
+{
+ uint len = length();
+ if ( m_data==0 || (uint)index>len ) // index outside string
+ return -1;
+ register const char *d;
+ if ( cs ) // case sensitive
+ {
+ d = strchr( m_data+index, c );
+ }
+ else
+ {
+ d = m_data+index;
+ c = tolower( (uchar) c );
+ while ( *d && tolower((uchar) *d) != c )
+ d++;
+ if ( !*d && c ) // not found
+ d = 0;
+ }
+ return d ? (int)(d - m_data) : -1;
+}
+
+int QCString::find( const char *str, int index, bool cs ) const
+{
+ uint l = length();
+ if ( m_data==0 || (uint)index > l ) // index outside string
+ return -1;
+ if ( !str ) // no search string
+ return -1;
+ if ( !*str ) // zero-length search string
+ return index;
+ register const char *d;
+ if ( cs ) // case sensitive
+ {
+ d = strstr( m_data+index, str );
+ }
+ else // case insensitive
+ {
+ d = m_data+index;
+ int len = qstrlen( str );
+ while ( *d )
{
- if (strncasecmp(pos,str,len)==0) break;
- pos++;
+ if ( qstrnicmp(d, str, len) == 0 )
+ break;
+ d++;
}
- if (!*pos) pos = 0; // not found
+ if ( !*d ) // not found
+ d = 0;
}
- return pos ? (int)(pos - data()) : -1;
+ return d ? (int)(d - m_data) : -1;
}
-int QCString::find( const QCString &str, int index, bool cs ) const
+int QCString::find( const QCString &str,int index,bool cs) const
{
return find(str.data(),index,cs);
}
int QCString::find( const QRegExp &rx, int index ) const
{
- QString d = QString::fromLatin1( data() );
+ QString d = QString::fromLatin1( m_data );
return d.find( rx, index );
}
int QCString::findRev( char c, int index, bool cs) const
{
-// printf("QCString::findRev(%d,%d,%d)\n",c,index,cs);
- const char *b = data();
- const char *pos;
- int len = length();
- if (len==0) return -1; // empty string
- if (index<0) // start from end
+ const char *b = m_data;
+ const char *d;
+ uint len = length();
+ if ( b == 0 ) return -1; // empty string
+ if ( index < 0 ) // neg index ==> start from end
{
- if (cs)
+ if ( len == 0 ) return -1;
+ if ( cs )
{
- pos = strrchr(b,c);
- return pos ? (int)(pos - b) : -1;
+ d = strrchr( b, c );
+ return d ? (int)(d - b) : -1;
}
- index=len;
- }
- else if (index>len) // bad index
- {
+ index = len;
+ }
+ else if ( (uint)index > len ) // bad index
+ {
return -1;
}
- pos = b+index;
- if (cs)
+ d = b+index;
+ if ( cs ) // case sensitive
{
- while ( pos>=b && *pos!=c) pos--;
- }
- else
+ while ( d >= b && *d != c )
+ d--;
+ }
+ else // case insensitive
{
- c = tolower((unsigned char)c);
- while ( pos>=b && tolower((unsigned char)*pos)!=c) pos--;
+ c = tolower( (uchar) c );
+ while ( d >= b && tolower((uchar) *d) != c )
+ d--;
}
- //printf("pos=%p b=%p diff=%d\n",pos,b,(int)(pos-b));
- return pos>=b ? (int)(pos - b) : -1;
+ return d >= b ? (int)(d - b) : -1;
}
int QCString::findRev( const char *str, int index, bool cs) const
{
- int slen = strlen(str);
- int len = length();
- if (index<0) index = len-slen; // start from end
- else if (index>len) return -1; // bad index
- else if (index+slen>len) index=len-slen; // str would be too long
- if (index<0) return -1; // no match possible
- register char *pos = data()+index;
- if (cs) // case sensitive
- {
- for (int i=index; i>=0; i--) if (strncmp(pos--,str,slen)==0) return i;
- }
- else // case insensitive
- {
- for (int i=index; i>=0; i--) if (strncasecmp(pos,str,slen)==0) return i;
+ int slen = qstrlen(str);
+ uint len = length();
+ if ( index < 0 ) // neg index ==> start from end
+ index = len-slen;
+ else if ( (uint)index > len ) // bad index
+ return -1;
+ else if ( (uint)(index + slen) > len ) // str would be too long
+ index = len - slen;
+ if ( index < 0 )
+ return -1;
+
+ register char *d = m_data + index;
+ if ( cs ) // case sensitive
+ {
+ for ( int i=index; i>=0; i-- )
+ if ( qstrncmp(d--,str,slen)==0 )
+ return i;
+ }
+ else // case insensitive
+ {
+ for ( int i=index; i>=0; i-- )
+ if ( qstrnicmp(d--,str,slen)==0 )
+ return i;
}
return -1;
+
}
int QCString::findRev( const QRegExp &rx, int index ) const
{
- QString d = QString::fromLatin1( data() );
+ QString d = QString::fromLatin1( m_data );
return d.findRev( rx, index );
}
int QCString::contains( char c, bool cs ) const
{
- if (length()==0) return 0;
- int count=0;
- const char *pos = data();
- if (cs)
- {
- while (*pos) if (*pos++ == c) count++;
- }
- else
- {
- c = tolower((unsigned char)c);
- while (*pos)
- {
- if (tolower((unsigned char)*pos)==c) count++;
- pos++;
+ int count = 0;
+ char *d = m_data;
+ if ( !d )
+ return 0;
+ if ( cs ) // case sensitive
+ {
+ while ( *d )
+ if ( *d++ == c )
+ count++;
+ }
+ else // case insensitive
+ {
+ c = tolower( (uchar) c );
+ while ( *d ) {
+ if ( tolower((uchar) *d) == c )
+ count++;
+ d++;
}
}
return count;
@@ -173,106 +306,96 @@ int QCString::contains( char c, bool cs ) const
int QCString::contains( const char *str, bool cs ) const
{
- if (str==0 || length()==0) return 0;
- int count=0;
- const char *pos = data();
- int len = strlen(str);
- while (*pos)
+ int count = 0;
+ char *d = data();
+ if ( !d )
+ return 0;
+ int len = qstrlen( str );
+ while ( *d ) // counts overlapping strings
{
- if (cs)
+ if ( cs )
{
- if (strncmp(pos,str,len)==0) count++;
- }
- else
+ if ( qstrncmp( d, str, len ) == 0 )
+ count++;
+ }
+ else
{
- if (strncasecmp(pos,str,len)==0) count++;
+ if ( qstrnicmp(d, str, len) == 0 )
+ count++;
}
- pos++;
+ d++;
}
return count;
}
int QCString::contains( const QRegExp &rx ) const
-{
- QString d = QString::fromLatin1( data() );
+{
+ QString d = QString::fromLatin1( m_data );
return d.contains( rx );
}
-bool QCString::stripPrefix(const char *prefix)
-{
- if (prefix==0 || length()==0) return FALSE;
- int len = strlen(prefix);
- if (strncmp(prefix,data(),len)==0)
- {
- int newlen = length()-len+1;
- qmemmove(data(),data()+len,newlen);
- resize(newlen);
- return TRUE;
- }
- return FALSE;
-}
-
QCString QCString::left( uint len ) const
{
- if (isEmpty())
+ if ( isEmpty() )
{
return QCString();
- }
- else if (len>=length())
+ }
+ else if ( len >= length() )
{
- return QCString(data());
- }
- else
+ return *this;
+ }
+ else
{
QCString s( len+1 );
- memcpy( s.data(), data(), len);
+ strncpy( s.data(), m_data, len );
+ *(s.data()+len) = '\0';
return s;
}
}
QCString QCString::right( uint len ) const
{
- if (isEmpty())
+ if ( isEmpty() )
{
return QCString();
- }
- else
+ }
+ else
{
- int l = length();
- if ((int)len>l) len=l;
- const char *pos = data() + (l-len);
- return QCString(pos);
- }
+ uint l = length();
+ if ( len > l ) len = l;
+ char *p = m_data + (l - len);
+ return QCString( p );
+ }
}
QCString QCString::mid( uint index, uint len) const
{
- int slen = length();
- if (len==0xffffffff) len = slen-index;
- if (isEmpty() || (int)index>=slen)
+ uint slen = length();
+ if ( len == 0xffffffff ) len = slen-index;
+ if ( isEmpty() || index >= slen )
{
return QCString();
- }
- else
+ }
+ else
{
register char *p = data()+index;
- QCString s(len+1);
- memcpy(s.data(),p,len);
+ QCString s( len+1 );
+ strncpy( s.data(), p, len );
+ *(s.data()+len) = '\0';
return s;
}
}
QCString QCString::lower() const
{
- if (length()==0) return QCString();
- QCString s(data());
- register char *pos = s.data();
- if (pos)
+ QCString s( m_data );
+ register char *p = s.data();
+ if ( p )
{
- while (*pos)
+ while ( *p )
{
- *pos = tolower((unsigned char)*pos);
- pos++;
+ *p = tolower((uchar) *p);
+ p++;
}
}
return s;
@@ -280,44 +403,41 @@ QCString QCString::lower() const
QCString QCString::upper() const
{
- if (length()==0) return QCString();
- QCString s(data());
- register char *pos = s.data();
- if (pos)
- {
- while (*pos)
- {
- *pos = toupper((unsigned char)*pos);
- pos++;
+ QCString s( m_data );
+ register char *p = s.data();
+ if ( p ) {
+ while ( *p ) {
+ *p = toupper((uchar)*p);
+ p++;
}
}
return s;
}
-QCString QCString::stripWhiteSpace() const
+QCString QCString::stripWhiteSpace() const
{
if ( isEmpty() ) // nothing to do
return *this;
- register char *s = data();
+ register char *s = m_data;
int reslen = length();
- if ( !isspace((uchar)s[0]) && !isspace((uchar)s[reslen-1]) )
- return *this; // returns a copy
+ if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) )
+ return *this; // returns a copy
QCString result(s);
- s = result.data();
+ s = result.data();
int start = 0;
int end = reslen - 1;
while ( isspace((uchar) s[start]) ) // skip white space from start
- start++;
- if ( s[start] == '\0' )
+ start++;
+ if ( s[start] == '\0' )
{ // only white space
return QCString();
}
while ( end && isspace((uchar) s[end]) ) // skip white space from end
end--;
end -= start - 1;
- qmemmove( result.data(), &s[start], end );
+ memmove( result.data(), &s[start], end );
result.resize( end + 1 );
return result;
}
@@ -331,7 +451,7 @@ QCString QCString::simplifyWhiteSpace() const
char *from = data();
char *to = result.data();
char *first = to;
- while ( TRUE )
+ while ( TRUE )
{
while ( *from && isspace((uchar) *from) )
from++;
@@ -349,66 +469,84 @@ QCString QCString::simplifyWhiteSpace() const
return result;
}
-QCString &QCString::assign( const char *str )
-{
- return operator=(str);
-}
-
QCString &QCString::insert( uint index, const char *s )
-{
+{
int len = s ? qstrlen(s) : 0;
- if ( len == 0 ) return *this;
- int olen = length();
- int nlen = olen + len;
- if ((int)index>=olen)
- {
- resize(nlen+index-olen+1);
- memset(data()+olen, ' ', index-olen);
- memcpy(data()+index,s, len+1);
- }
- else
- {
- resize(nlen+1);
- qmemmove(data()+index+len,data()+index,olen-index+1);
- memcpy(data()+index,s,len);
+ if ( len == 0 )
+ return *this;
+ uint olen = length();
+ int nlen = olen + len;
+ if ( index >= olen ) // insert after end of string
+ {
+ m_data = (char *)realloc(m_data,nlen+index-olen+1);
+ if ( m_data )
+ {
+ memset( m_data+olen, ' ', index-olen );
+ memcpy( m_data+index, s, len+1 );
+ }
+ }
+ else if ( (m_data = (char *)realloc(m_data,nlen+1)) ) // normal insert
+ {
+ memmove( m_data+index+len, m_data+index, olen-index+1 );
+ memcpy( m_data+index, s, len );
}
return *this;
}
-QCString &QCString::insert( uint index, char c)
+QCString &QCString::insert( uint index, char c ) // insert char
{
char buf[2];
buf[0] = c;
buf[1] = '\0';
return insert( index, buf );
}
-QCString &QCString::append( const char *s )
+
+QCString& QCString::operator+=( const char *str )
{
- return operator+=(s);
+ if ( !str ) return *this; // nothing to append
+ uint len1 = length();
+ uint len2 = qstrlen(str);
+ char *newData = (char *)realloc( m_data, len1 + len2 + 1 );
+ if (newData)
+ {
+ m_data = newData;
+ memcpy( m_data + len1, str, len2 + 1 );
+ }
+ return *this;
}
-QCString &QCString::prepend( const char *s )
+
+QCString &QCString::operator+=( char c )
{
- return insert(0,s);
+ uint len = length();
+ char *newData = (char *)realloc( m_data, length()+2 );
+ if (newData)
+ {
+ m_data = newData;
+ m_data[len] = c;
+ m_data[len+1] = '\0';
+ }
+ return *this;
}
+
QCString &QCString::remove( uint index, uint len )
{
uint olen = length();
if ( index + len >= olen ) // range problems
- {
+ {
if ( index < olen ) // index ok
- {
+ {
resize( index+1 );
}
- }
- else if ( len != 0 )
+ }
+ else if ( len != 0 )
{
- qmemmove( data()+index, data()+index+len, olen-index-len+1 );
+ memmove( m_data+index, m_data+index+len, olen-index-len+1 );
resize( olen-len+1 );
}
return *this;
}
-QCString &QCString::replace( uint index, uint len, const char *s)
+QCString &QCString::replace( uint index, uint len, const char *s )
{
remove( index, len );
insert( index, s );
@@ -417,85 +555,65 @@ QCString &QCString::replace( uint index, uint len, const char *s)
QCString &QCString::replace( const QRegExp &rx, const char *str )
{
- QString d = QString::fromLatin1( data() );
+ QString d = QString::fromLatin1( m_data );
QString r = QString::fromLatin1( str );
d.replace( rx, r );
operator=( d.ascii() );
return *this;
}
-short QCString::toShort(bool *ok) const
-{
- QString s(data());
- return s.toShort(ok);
-}
-
-ushort QCString::toUShort(bool *ok) const
-{
- QString s(data());
- return s.toUShort(ok);
-}
-
-int QCString::toInt(bool *ok) const
-{
- QString s(data());
- return s.toInt(ok);
-}
-
-uint QCString::toUInt(bool *ok) const
-{
- QString s(data());
- return s.toUInt(ok);
-}
-
-long QCString::toLong(bool *ok) const
+long QCString::toLong( bool *ok ) const
{
- QString s(data());
+ QString s(m_data);
return s.toLong(ok);
}
-ulong QCString::toULong(bool *ok) const
+ulong QCString::toULong( bool *ok ) const
{
- QString s(data());
+ QString s(m_data);
return s.toULong(ok);
}
-QCString &QCString::setNum(short n)
+short QCString::toShort( bool *ok ) const
{
- return setNum((long)n);
+ QString s(m_data);
+ return s.toShort(ok);
}
-QCString &QCString::setNum(ushort n)
+ushort QCString::toUShort( bool *ok ) const
{
- return setNum((ulong)n);
+ QString s(m_data);
+ return s.toUShort(ok);
}
-QCString &QCString::setNum(int n)
+int QCString::toInt( bool *ok ) const
{
- return setNum((long)n);
+ QString s(m_data);
+ return s.toInt(ok);
}
-QCString &QCString::setNum(uint n)
+uint QCString::toUInt( bool *ok ) const
{
- return setNum((ulong)n);
+ QString s(m_data);
+ return s.toUInt(ok);
}
-QCString &QCString::setNum(long n)
+QCString &QCString::setNum( long n )
{
char buf[20];
register char *p = &buf[19];
bool neg;
- if ( n < 0 )
+ if ( n < 0 )
{
neg = TRUE;
n = -n;
- }
- else
+ }
+ else
{
neg = FALSE;
}
*p = '\0';
- do
+ do
{
*--p = ((int)(n%10)) + '0';
n /= 10;
@@ -505,12 +623,12 @@ QCString &QCString::setNum(long n)
return *this;
}
-QCString &QCString::setNum( ulong n)
+QCString &QCString::setNum( ulong n )
{
char buf[20];
register char *p = &buf[19];
*p = '\0';
- do
+ do
{
*--p = ((int)(n%10)) + '0';
n /= 10;
@@ -519,7 +637,31 @@ QCString &QCString::setNum( ulong n)
return *this;
}
-//-------------------------------------------------
+void QCString::msg_index( uint index )
+{
+#if defined(CHECK_RANGE)
+ qWarning( "QCString::at: Absolute index %d out of range", index );
+#else
+ Q_UNUSED( index )
+#endif
+}
+
+bool QCString::stripPrefix(const char *prefix)
+{
+ if (prefix==0) return FALSE;
+ uint plen = qstrlen(prefix);
+ if (m_data && qstrncmp(prefix,m_data,plen)==0) // prefix matches
+ {
+ uint len = qstrlen(m_data);
+ uint newlen = len-plen+1;
+ qmemmove(m_data,m_data+plen,newlen);
+ resize(newlen);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
void *qmemmove( void *dst, const void *src, uint len )
{
diff --git a/qtools/qcstring.h b/qtools/qcstring.h
index 8acd9ff..f7d2c95 100644
--- a/qtools/qcstring.h
+++ b/qtools/qcstring.h
@@ -1,16 +1,38 @@
/****************************************************************************
+**
**
-** Copyright (C) 1997-2004 by Dimitri van Heesch.
+** Definition of the extended char array operations,
+** and QByteArray and QCString classes
**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation under the terms of the GNU General Public License is hereby
-** granted. No representations are made about the suitability of this software
-** for any purpose. It is provided "as is" without express or implied warranty.
-** See the GNU General Public License for more details.
+** Created : 920609
**
-** Note: this is a reimplementation of the qcstring.h that came with
-** an Qt version 2.2.3. For short strings it stores the string data inside
-** the object. For long strings it uses a separate array with reference counting.
+** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
+**
+** This file is part of the tools module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
**
**********************************************************************/
@@ -21,7 +43,6 @@
#include "qarray.h"
#endif // QT_H
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,7 +54,6 @@
#include <strings.h>
#endif
-#include <assert.h>
class QGString;
@@ -57,6 +77,7 @@ inline char *hack_strrchr( const char *s, int c )
#define strrchr(s,c) hack_strrchr((s),(c))
#endif
+
/*****************************************************************************
Safe and portable C string functions; extensions to standard string.h
*****************************************************************************/
@@ -106,6 +127,39 @@ Q_EXPORT int qstricmp( const char *str1, const char *str2 );
Q_EXPORT int qstrnicmp( const char *str1, const char *str2, uint len );
+#if 0
+// ### TODO for 3.0: these and the cstr* functions should be used if
+// !defined(QT_CLEAN_NAMESPACE)
+// We want to keep source compatibility for 2.x
+// ### TODO for 4.0: completely remove these and the cstr* functions
+
+#if !defined(QT_GENUINE_STR)
+
+#undef strlen
+#define strlen qstrlen
+
+#undef strcpy
+#define strcpy qstrcpy
+
+#undef strcmp
+#define strcmp qstrcmp
+
+#undef strncmp
+#define strncmp qstrncmp
+
+#undef stricmp
+#define stricmp qstricmp
+
+#undef strnicmp
+#define strnicmp qstrnicmp
+
+#endif
+#endif
+
+// qChecksum: Internet checksum
+
+Q_EXPORT Q_UINT16 qChecksum( const char *s, uint len );
+
/*****************************************************************************
QByteArray class
*****************************************************************************/
@@ -115,6 +169,7 @@ template class Q_EXPORT QArray<char>;
#endif
typedef QArray<char> QByteArray;
+
/*****************************************************************************
QByteArray stream functions
*****************************************************************************/
@@ -126,541 +181,143 @@ Q_EXPORT QDataStream &operator>>( QDataStream &, QByteArray & );
class QRegExp;
/** This is an alternative implementation of QCString. It provides basically
- * the same functions but uses reference counting and copy on write.
+ * the same functions but uses less memory for administration. This class
+ * is just a wrapper around a plain C string requiring only 4 bytes "overhead".
+ * QCString features sharing of data and stores the string length, but
+ * requires 4 + 12 bytes for this (even for the empty string). As doxygen
+ * uses a LOT of string during a run it saves a lot of memory to use a
+ * more memory efficient implementation at the cost of relatively low
+ * runtime overhead.
*/
-class QCString
+class QCString
{
public:
- /** creates an empty string */
- QCString()
- {
- }
-
- /** destroys the string */
- ~QCString()
- {
- }
-
- /** makes a copy of a string. */
- QCString( const QCString &s ) : m_rep(s.m_rep)
- {
- }
-
- /** creates a string with room for size characters
- * @param[in] size the number of character to allocate (including the 0-terminator)
- */
- QCString( int size ) : m_rep(size)
- {
- }
-
- /** creates a string from a plain C string.
- * @param[in] str A zero terminated C string. When 0 an empty string is created.
- */
- QCString( const char *str ) : m_rep(str)
- {
- }
-
- /** creates a string from \a str and copies over the first \a maxlen characters. */
- QCString( const char *str, uint maxlen ) : m_rep(str,maxlen)
- {
- }
-
- /** replaces the contents by that of string \a s. */
- QCString &operator=( const QCString &s )
- {
- m_rep = s.m_rep;
- return *this;
- }
-
- /** replaces the contents by that of C string \a str. */
- QCString &operator=( const char *str)
- {
- m_rep = str;
- return *this;
- }
-
- /** Returns TRUE iff the string is empty. Equivalent to isEmpty(). */
- bool isNull() const
- {
- return m_rep.isEmpty();
- }
-
- /** Returns TRUE iff the string is empty */
- bool isEmpty() const
- {
- return m_rep.isEmpty();
- }
-
- /** Returns the length of the string, excluding the 0-terminator. Equivalent to size(). */
- uint length() const
- {
- return m_rep.length();
- }
-
- /** Returns the length of the string, excluding the 0-terminator. */
- uint size() const
- {
- return m_rep.length();
- }
-
- /** Returns a pointer to the contents of the string in the form of a 0-terminated C string */
- char *data() const
- {
- return m_rep.data();
- }
-
- /** Resizes the string to hold \a newlen characters
- * (this value should include the 0-terminator). If the string is enlarged the contents will
- * be left unmodified.
- */
- bool resize( uint newlen )
- {
- m_rep.resize(newlen);
- return TRUE;
- }
-
- /** Truncates the string at position \a pos. */
- bool truncate( uint pos )
- {
- return resize(pos+1);
- }
-
- /** Fills a string with a predefined character
- * @param[in] c the character used to fill the string with.
- * @param[in] len the number of character to fill. Use -1 to fill the whole string.
- * @note the string will be resized to contain \a len characters. The contents of the
- * string will be lost.
- */
- bool fill( char c, int len = -1 )
- {
- m_rep.fill(c,len);
- return TRUE;
- }
-
- /** Returns a deep copy of the string. */
- QCString copy() const
- {
- if (length()==0) return QCString();
- QCString cs(length()+1);
- memcpy(cs.data(),data(),length());
- return cs;
- }
-
- QCString &sprintf( const char *format, ... );
- int find( char c, int index=0, bool cs=TRUE ) const;
- int find( const char *str, int index=0, bool cs=TRUE ) const;
- int find( const QCString &str, int index=0, bool cs=TRUE ) const;
- int find( const QRegExp &rx, int index=0 ) const;
- int findRev( char c, int index=-1, bool cs=TRUE) const;
- int findRev( const char *str, int index=-1, bool cs=TRUE) const;
- int findRev( const QRegExp &rx, int index=-1 ) const;
- int contains( char c, bool cs=TRUE ) const;
- int contains( const char *str, bool cs=TRUE ) const;
- int contains( const QRegExp &rx ) const;
- bool stripPrefix(const char *prefix);
- QCString left( uint len ) const;
- QCString right( uint len ) const;
- QCString mid( uint index, uint len=0xffffffff) const;
- QCString lower() const;
- QCString upper() const;
- QCString stripWhiteSpace() const;
- QCString simplifyWhiteSpace() const;
- QCString &assign( const char *str );
- QCString &insert( uint index, const char *s );
- QCString &insert( uint index, char c);
- QCString &append( const char *s );
- QCString &prepend( const char *s );
- QCString &remove( uint index, uint len );
- QCString &replace( uint index, uint len, const char *s);
- QCString &replace( const QRegExp &rx, const char *str );
- short toShort( bool *ok=0 ) const;
- ushort toUShort( bool *ok=0 ) const;
- int toInt( bool *ok=0 ) const;
- uint toUInt( bool *ok=0 ) const;
- long toLong( bool *ok=0 ) const;
- ulong toULong( bool *ok=0 ) const;
- QCString &setNum(short n);
- QCString &setNum(ushort n);
- QCString &setNum(int n);
- QCString &setNum(uint n);
- QCString &setNum(long n);
- QCString &setNum(ulong n);
-
- /** Converts the string to a plain C string */
- operator const char *() const
- {
- return (const char *)data();
- }
-
- /** Appends string \a str to this string and returns a reference to the result. */
- QCString &operator+=( const char *str )
- {
- if (!str) return *this;
- int len1 = length();
- int len2 = strlen(str);
- resize(len1+len2+1);
- memcpy(data()+len1,str,len2);
- return *this;
- }
-
- /** Appends character \a c to this string and returns a reference to the result. */
- QCString &operator+=( char c )
- {
- int len = length();
- resize(len+2);
- data()[len]=c;
- return *this;
- }
-
- /** Returns a reference to the character at index \a i. */
- char &at( uint i) const
- {
- return m_rep.at(i);
- }
-
- /** Indexing operator. Equavalent to at(). */
- char &operator[]( int i ) const
- {
- return m_rep.at((uint)i);
- }
-
+ QCString() : m_data(0) {} // make null string
+ QCString( const QCString &s );
+ QCString( int size );
+ QCString( const char *str );
+ QCString( const char *str, uint maxlen );
+ ~QCString();
+
+ QCString &operator=( const QCString &s );// deep copy
+ QCString &operator=( const char *str ); // deep copy
+
+ bool isNull() const;
+ bool isEmpty() const;
+ uint length() const;
+ uint size() const { return m_data ? length()+1 : 0; }
+ char * data() const { return m_data; }
+ bool resize( uint newlen );
+ bool truncate( uint pos );
+ bool fill( char c, int len = -1 );
+
+ QCString copy() const;
+
+ QCString &sprintf( const char *format, ... );
+
+ int find( char c, int index=0, bool cs=TRUE ) const;
+ int find( const char *str, int index=0, bool cs=TRUE ) const;
+ int find( const QCString &str, int index=0, bool cs=TRUE ) const;
+ int find( const QRegExp &, int index=0 ) const;
+ int findRev( char c, int index=-1, bool cs=TRUE) const;
+ int findRev( const char *str, int index=-1, bool cs=TRUE) const;
+ int findRev( const QRegExp &, int index=-1 ) const;
+ int contains( char c, bool cs=TRUE ) const;
+ int contains( const char *str, bool cs=TRUE ) const;
+ int contains( const QRegExp & ) const;
+ bool stripPrefix(const char *prefix);
+
+ QCString left( uint len ) const;
+ QCString right( uint len ) const;
+ QCString mid( uint index, uint len=0xffffffff) const;
+
+ QCString lower() const;
+ QCString upper() const;
+
+ QCString stripWhiteSpace() const;
+ QCString simplifyWhiteSpace() const;
+
+ QCString &assign( const char *str );
+ QCString &insert( uint index, const char * );
+ QCString &insert( uint index, char );
+ QCString &append( const char *s );
+ QCString &prepend( const char *s );
+ QCString &remove( uint index, uint len );
+ QCString &replace( uint index, uint len, const char * );
+ QCString &replace( const QRegExp &, const char * );
+
+ short toShort( bool *ok=0 ) const;
+ ushort toUShort( bool *ok=0 ) const;
+ int toInt( bool *ok=0 ) const;
+ uint toUInt( bool *ok=0 ) const;
+ long toLong( bool *ok=0 ) const;
+ ulong toULong( bool *ok=0 ) const;
+
+ QCString &setNum( short );
+ QCString &setNum( ushort );
+ QCString &setNum( int );
+ QCString &setNum( uint );
+ QCString &setNum( long );
+ QCString &setNum( ulong );
+ QCString &setNum( float, char f='g', int prec=6 );
+ QCString &setNum( double, char f='g', int prec=6 );
+
+ operator const char *() const;
+ QCString &operator+=( const char *str );
+ QCString &operator+=( char c );
+ char &at( uint index ) const;
+ char &operator[]( int i ) const { return at(i); }
+
private:
+ static void msg_index( uint );
+ void duplicate( const QCString &s );
+ void duplicate( const char *str);
+ QCString &duplicate( const char *str, int);
- struct LSData;
-
- // long string representation
- struct LongStringRep
- {
- uchar isShort : 1; // should be shared with ShortStringRep
- uchar : 7;
- LSData *d;
- };
-
-#define SHORT_STR_CAPACITY ((int)sizeof(LongStringRep)-1)
-#define SHORT_STR_MAX_LEN (SHORT_STR_CAPACITY-1)
-
- // short string representation
- struct ShortStringRep
- {
- uchar isShort : 1; // should be shared with LongStringRep
- uchar len : 7;
- char str[SHORT_STR_CAPACITY]; // size including 0-terminator
- };
-
- // ref counting string header
- struct LSHeader
- {
- int len; // length of string without 0 terminator
- int refCount; // -1=leaked, 0=one ref & non-cost, n>0, n+1 refs, const
- };
- // ref counting string data and methods
- struct LSData : public LSHeader
- {
- char *toStr()
- {
- return (char*)(this+1); // string data starts after the header
- }
-
- // creates a LSData item with room for size bytes (which includes the 0 terminator!)
- // if size is zero, an empty string will be created.
- static LSData *create(int size)
- {
- LSData *data;
- data = (LSData*)malloc(sizeof(LSHeader)+size);
- data->len = size-1;
- data->refCount = 0;
- data->toStr()[size-1] = 0;
- return data;
- }
- // remove out reference to the data. Frees memory if no more users
- void dispose()
- {
- if (--refCount<0) free(this);
- }
-
- // resizes LSData so it can hold size bytes (which includes the 0 terminator!)
- // Since this is for long strings only, size should be > SHORT_STR_CAPACITY
- static LSData *resize(LSData *d,int size)
- {
- if (d->len>0 && d->refCount==0) // non-const, non-empty
- {
- d = (LSData*)realloc(d,sizeof(LSHeader)+size);
- d->len = size-1;
- d->toStr()[size-1] = 0;
- return d;
- }
- else // need to make a copy
- {
- LSData *newData = LSData::create(size);
- int len = d->len;
- if (len>=size) len=size-1;
- memcpy(newData->toStr(),d->toStr(),len);
- newData->toStr()[len]=0;
- d->dispose();
- return newData;
- }
- }
- };
-
- class StringRep
- {
- public:
- StringRep()
- {
- u.s.isShort=TRUE;
- u.s.len=0;
- }
- ~StringRep()
- {
- if (!u.s.isShort)
- {
- u.l.d->dispose();
- }
- }
- StringRep(const StringRep &s)
- {
- if (&s!=this)
- {
- u = s.u;
- if (!u.s.isShort)
- {
- u.l.d->refCount++;
- }
- }
- }
- StringRep(int size)
- {
- u.s.isShort = size<=SHORT_STR_CAPACITY;
- if (size<=SHORT_STR_CAPACITY) // init short string
- {
- if (size>0)
- {
- u.s.len = size-1;
- u.s.str[size-1]='\0';
- }
- else
- {
- u.s.len = 0;
- }
- }
- else // int long string
- {
- u.l.d = LSData::create(size);
- }
- }
- StringRep(const char *str)
- {
- if (str)
- {
- int len = strlen(str);
- u.s.isShort = len<SHORT_STR_CAPACITY;
- if (len<SHORT_STR_CAPACITY)
- {
- u.s.len = len;
- memcpy(u.s.str,str,len+1);
- }
- else
- {
- u.l.d = LSData::create(len+1);
- memcpy(u.l.d->toStr(),str,u.l.d->len);
- }
- }
- else // create empty string
- {
- u.s.isShort=TRUE;
- u.s.len=0;
- }
- }
- StringRep( const char *str, uint maxlen )
- {
- if (str && maxlen>0)
- {
- uint len=strlen(str);
- if (len>maxlen) len=maxlen;
- u.s.isShort = len<=SHORT_STR_MAX_LEN;
- if (u.s.isShort)
- {
- u.s.len = len;
- memcpy(u.s.str,str,len);
- u.s.str[len]='\0';
- }
- else
- {
- u.l.d = LSData::create(len+1);
- memcpy(u.l.d->toStr(),str,len);
- }
- }
- else // create empty string
- {
- u.s.isShort=TRUE;
- u.s.len=0;
- }
- }
- StringRep &operator=(const StringRep &s)
- {
- if (&s!=this)
- {
- if (!u.s.isShort)
- {
- u.l.d->dispose();
- }
- if (s.u.s.isShort) // copy by value
- {
- u.s = s.u.s;
- }
- else // copy by reference
- {
- u.l.isShort=FALSE;
- u.l.d = s.u.l.d;
- u.l.d->refCount++;
- }
- }
- return *this;
- }
- StringRep &operator=(const char *str)
- {
- if (!u.s.isShort)
- {
- u.l.d->dispose();
- }
- if (str)
- {
- int len = strlen(str);
- u.s.isShort = len<=SHORT_STR_MAX_LEN;
- if (len<SHORT_STR_CAPACITY)
- {
- u.s.len = len;
- memcpy(u.s.str,str,len+1);
- }
- else
- {
- u.l.d = LSData::create(len+1);
- memcpy(u.l.d->toStr(),str,u.l.d->len);
- }
- }
- else
- {
- u.s.isShort=TRUE;
- u.s.len=0;
- }
- return *this;
- }
- bool isEmpty() const
- {
- return u.s.isShort && u.s.len==0;
- }
- uint length() const
- {
- return u.s.isShort ? u.s.len : u.l.d->len;
- }
- char *data() const
- {
- if (u.s.isShort)
- {
- return u.s.len==0 ? 0 : (char*)u.s.str;
- }
- else
- {
- return u.l.d->len==0 ? 0 : u.l.d->toStr();
- }
- }
- char &at(int i) const
- {
- if (u.s.isShort)
- {
- return (char&)u.s.str[i];
- }
- else
- {
- return u.l.d->toStr()[i];
- }
- }
- bool resize( uint newlen )
- {
- if (u.s.isShort && newlen<=SHORT_STR_CAPACITY) // resize short string
- {
- if (newlen>0)
- {
- u.s.len = newlen-1;
- u.s.str[newlen-1]='\0';
- }
- else // string becomes empty
- {
- u.s.len = 0;
- }
- }
- else if (u.s.isShort) // turn short string into long string
- {
- StringRep tmp = *this;
- u.s.isShort=FALSE;
- u.l.d = LSData::create(newlen);
- if (tmp.u.s.len>0)
- {
- memcpy(u.l.d->toStr(),tmp.u.s.str,tmp.u.s.len+1);
- }
- else
- {
- u.l.d->toStr()[0]='\0';
- }
- }
- else if (!u.s.isShort && newlen<=SHORT_STR_CAPACITY) // turn long string into short string
- {
- if (newlen>0)
- {
- StringRep tmp(newlen); // copy short part into tmp buffer
- memcpy(tmp.u.s.str,u.l.d->toStr(),newlen-1);
- tmp.u.s.str[newlen-1]='\0';
- u.l.d->dispose();
- u.s = tmp.u.s;
- }
- else
- {
- u.l.d->dispose();
- u.s.isShort=TRUE;
- u.s.len=0;
- }
- }
- else // resize long string
- {
- u.l.d = u.l.d->resize(u.l.d,newlen);
- }
- return TRUE;
- }
- bool fill( char c, int len )
- {
- if (len<0) len=length();
- if (len!=(int)length())
- {
- if (len>0)
- {
- resize(len+1);
- }
- else
- {
- if (!u.s.isShort)
- {
- u.l.d->dispose();
- }
- u.s.isShort=TRUE;
- u.s.len=0;
- }
- }
- if (len>0)
- {
- memset(data(),c,len);
- }
- return TRUE;
- }
- private:
- union
- {
- ShortStringRep s;
- LongStringRep l;
- } u;
- };
- StringRep m_rep;
+ char * m_data;
};
+inline char &QCString::at( uint index ) const
+{
+ return m_data[index];
+}
+
+inline void QCString::duplicate( const QCString &s )
+{
+ if (!s.isEmpty())
+ {
+ uint l = (uint)strlen(s.data());
+ m_data = (char *)malloc(l+1);
+ if (m_data) memcpy(m_data,s.data(),l+1);
+ }
+ else
+ {
+ m_data=0;
+ }
+}
+
+inline void QCString::duplicate( const char *str)
+{
+ if (str && str[0]!='\0')
+ {
+ uint l = (uint)strlen(str);
+ m_data = (char *)malloc(l+1);
+ if (m_data) memcpy(m_data,str,l+1);
+ }
+ else
+ {
+ m_data=0;
+ }
+}
+
+inline QCString &QCString::duplicate( const char *str, int)
+{
+ if (m_data==str) return *this;
+ if (m_data) free(m_data);
+ duplicate(str);
+ return *this;
+}
+
/*****************************************************************************
QCString stream functions
*****************************************************************************/
@@ -670,6 +327,56 @@ Q_EXPORT QDataStream &operator>>( QDataStream &, QCString & );
#endif
/*****************************************************************************
+ QCString inline functions
+ *****************************************************************************/
+
+inline QCString &QCString::operator=( const QCString &s )
+{ return (QCString&)assign( s ); }
+
+inline QCString &QCString::operator=( const char *str )
+{ return (QCString&)duplicate( str, qstrlen(str)+1 ); }
+
+inline bool QCString::isNull() const
+{ return data() == 0; }
+
+inline bool QCString::isEmpty() const
+{ return data() == 0 || *data() == '\0'; }
+
+inline uint QCString::length() const
+{ return qstrlen( data() ); }
+
+inline bool QCString::truncate( uint pos )
+{ return resize(pos+1); }
+
+inline QCString QCString::copy() const
+{ return QCString( data() ); }
+
+inline QCString &QCString::prepend( const char *s )
+{ return insert(0,s); }
+
+inline QCString &QCString::append( const char *s )
+{ return operator+=(s); }
+
+inline QCString &QCString::setNum( short n )
+{ return setNum((long)n); }
+
+inline QCString &QCString::setNum( ushort n )
+{ return setNum((ulong)n); }
+
+inline QCString &QCString::setNum( int n )
+{ return setNum((long)n); }
+
+inline QCString &QCString::setNum( uint n )
+{ return setNum((ulong)n); }
+
+inline QCString &QCString::setNum( float n, char f, int prec )
+{ return setNum((double)n,f,prec); }
+
+inline QCString::operator const char *() const
+{ return (const char *)data(); }
+
+
+/*****************************************************************************
QCString non-member operators
*****************************************************************************/
@@ -769,4 +476,5 @@ inline const char *qPrint(const QCString &s)
if (!s.isEmpty()) return s.data(); else return "";
}
+
#endif // QCSTRING_H
diff --git a/qtools/qtools.pro.in b/qtools/qtools.pro.in
index ba8a086..f287d34 100644
--- a/qtools/qtools.pro.in
+++ b/qtools/qtools.pro.in
@@ -7,6 +7,7 @@ HEADERS = qarray.h \
qcollection.h \
qconfig.h \
qcstring.h \
+ scstring.h \
qdatastream.h \
qdatetime.h \
qdict.h \
@@ -53,7 +54,7 @@ HEADERS = qarray.h \
SOURCES = qbuffer.cpp \
qcollection.cpp \
- qcstring.cpp \
+ scstring.cpp \
qdatastream.cpp \
qdatetime.cpp \
qdir.cpp \
diff --git a/qtools/scstring.cpp b/qtools/scstring.cpp
new file mode 100644
index 0000000..26d3a52
--- /dev/null
+++ b/qtools/scstring.cpp
@@ -0,0 +1,798 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2004 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+// with this switch you can choose between the original qcstring implementation,
+// which implicitly shares data so copying is faster, but requires at least 12 bytes, and
+// the new implementation in this file, which has a smaller footprint (only 4 bytes for
+// an empty string), but always copies strings.
+#define SMALLSTRING
+
+#include "qcstring.h"
+#ifndef SMALLSTRING
+#include "qcstring.cpp"
+#else
+#define SCString QCString
+
+#include <qstring.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <qregexp.h>
+#include <qdatastream.h>
+
+
+SCString::SCString(int size)
+{
+ if (size>0)
+ {
+ m_data = (char *)malloc(size);
+ if (m_data)
+ {
+ if (size>1) memset(m_data,' ',size-1);
+ m_data[size-1]='\0';
+ }
+ }
+ else
+ {
+ m_data=0;
+ }
+}
+
+SCString::SCString( const SCString &s )
+{
+ duplicate(s);
+}
+
+SCString::SCString( const char *str )
+{
+ duplicate(str);
+}
+
+SCString::SCString( const char *str, uint maxlen )
+{
+ uint l;
+ if (str && ( l = QMIN(qstrlen(str),maxlen) ))
+ {
+ m_data=(char *)malloc(l+1);
+ strncpy(m_data,str,l+1);
+ m_data[l]='\0';
+ }
+ else
+ {
+ m_data=0;
+ }
+}
+
+SCString::~SCString()
+{
+ if (m_data) free(m_data);
+ m_data=0;
+}
+
+SCString &SCString::assign( const char *str )
+{
+ if (m_data==str) return *this;
+ if (m_data) free(m_data);
+ duplicate(str);
+ return *this;
+}
+
+bool SCString::resize( uint newlen )
+{
+ if (newlen==0)
+ {
+ if (m_data) { free(m_data); m_data=0; }
+ return TRUE;
+ }
+ if (m_data==0) // newlen>0
+ {
+ m_data = (char *)malloc(newlen);
+ }
+ else
+ {
+ m_data = (char *)realloc(m_data,newlen);
+ }
+ if (m_data==0) return FALSE;
+ m_data[newlen-1]='\0';
+ return TRUE;
+}
+
+bool SCString::fill( char c, int len )
+{
+ uint l=length();
+ if (len<0) len=l;
+ if ((uint)len!=l)
+ {
+ if (m_data) free(m_data);
+ if (len>0)
+ {
+ m_data=(char *)malloc(len+1);
+ if (m_data==0) return FALSE;
+ m_data[len]='\0';
+ }
+ else
+ {
+ m_data=0;
+ }
+ }
+ if (len>0)
+ {
+ uint i;
+ for (i=0;i<(uint)len;i++) m_data[i]=c;
+ }
+ return TRUE;
+}
+
+SCString &SCString::sprintf( const char *format, ... )
+{
+ va_list ap;
+ va_start( ap, format );
+ uint l = length();
+ const uint minlen=4095;
+ if (l<minlen)
+ {
+ if (m_data)
+ m_data = (char *)realloc(m_data,minlen+1);
+ else
+ m_data = (char *)malloc(minlen+1);
+ m_data[minlen]='\0';
+ }
+ vsnprintf( m_data, minlen, format, ap );
+ resize( qstrlen(m_data) + 1 ); // truncate
+ va_end( ap );
+ return *this;
+}
+
+
+int SCString::find( char c, int index, bool cs ) const
+{
+ uint len = length();
+ if ( m_data==0 || (uint)index>len ) // index outside string
+ return -1;
+ register const char *d;
+ if ( cs ) // case sensitive
+ {
+ d = strchr( m_data+index, c );
+ }
+ else
+ {
+ d = m_data+index;
+ c = tolower( (uchar) c );
+ while ( *d && tolower((uchar) *d) != c )
+ d++;
+ if ( !*d && c ) // not found
+ d = 0;
+ }
+ return d ? (int)(d - m_data) : -1;
+}
+
+int SCString::find( const char *str, int index, bool cs ) const
+{
+ uint l = length();
+ if ( m_data==0 || (uint)index > l ) // index outside string
+ return -1;
+ if ( !str ) // no search string
+ return -1;
+ if ( !*str ) // zero-length search string
+ return index;
+ register const char *d;
+ if ( cs ) // case sensitive
+ {
+ d = strstr( m_data+index, str );
+ }
+ else // case insensitive
+ {
+ d = m_data+index;
+ int len = qstrlen( str );
+ while ( *d )
+ {
+ if ( qstrnicmp(d, str, len) == 0 )
+ break;
+ d++;
+ }
+ if ( !*d ) // not found
+ d = 0;
+ }
+ return d ? (int)(d - m_data) : -1;
+}
+
+int SCString::find( const QCString &str, int index, bool cs ) const
+{
+ return find(str.data(),index,cs);
+}
+
+int SCString::find( const QRegExp &rx, int index ) const
+{
+ QString d = QString::fromLatin1( m_data );
+ return d.find( rx, index );
+}
+
+int SCString::findRev( char c, int index, bool cs) const
+{
+ const char *b = m_data;
+ const char *d;
+ uint len = length();
+ if ( b == 0 ) return -1; // empty string
+ if ( index < 0 ) // neg index ==> start from end
+ {
+ if ( len == 0 ) return -1;
+ if ( cs )
+ {
+ d = strrchr( b, c );
+ return d ? (int)(d - b) : -1;
+ }
+ index = len;
+ }
+ else if ( (uint)index > len ) // bad index
+ {
+ return -1;
+ }
+ d = b+index;
+ if ( cs ) // case sensitive
+ {
+ while ( d >= b && *d != c )
+ d--;
+ }
+ else // case insensitive
+ {
+ c = tolower( (uchar) c );
+ while ( d >= b && tolower((uchar) *d) != c )
+ d--;
+ }
+ return d >= b ? (int)(d - b) : -1;
+}
+
+int SCString::findRev( const char *str, int index, bool cs) const
+{
+ int slen = qstrlen(str);
+ uint len = length();
+ if ( index < 0 ) // neg index ==> start from end
+ index = len-slen;
+ else if ( (uint)index > len ) // bad index
+ return -1;
+ else if ( (uint)(index + slen) > len ) // str would be too long
+ index = len - slen;
+ if ( index < 0 )
+ return -1;
+
+ register char *d = m_data + index;
+ if ( cs ) // case sensitive
+ {
+ for ( int i=index; i>=0; i-- )
+ if ( qstrncmp(d--,str,slen)==0 )
+ return i;
+ }
+ else // case insensitive
+ {
+ for ( int i=index; i>=0; i-- )
+ if ( qstrnicmp(d--,str,slen)==0 )
+ return i;
+ }
+ return -1;
+
+}
+
+int SCString::findRev( const QRegExp &rx, int index ) const
+{
+ QString d = QString::fromLatin1( m_data );
+ return d.findRev( rx, index );
+}
+
+int SCString::contains( char c, bool cs ) const
+{
+ int count = 0;
+ char *d = m_data;
+ if ( !d )
+ return 0;
+ if ( cs ) // case sensitive
+ {
+ while ( *d )
+ if ( *d++ == c )
+ count++;
+ }
+ else // case insensitive
+ {
+ c = tolower( (uchar) c );
+ while ( *d ) {
+ if ( tolower((uchar) *d) == c )
+ count++;
+ d++;
+ }
+ }
+ return count;
+}
+
+int SCString::contains( const char *str, bool cs ) const
+{
+ int count = 0;
+ char *d = data();
+ if ( !d )
+ return 0;
+ int len = qstrlen( str );
+ while ( *d ) // counts overlapping strings
+ {
+ if ( cs )
+ {
+ if ( qstrncmp( d, str, len ) == 0 )
+ count++;
+ }
+ else
+ {
+ if ( qstrnicmp(d, str, len) == 0 )
+ count++;
+ }
+ d++;
+ }
+ return count;
+}
+
+int SCString::contains( const QRegExp &rx ) const
+{
+ QString d = QString::fromLatin1( m_data );
+ return d.contains( rx );
+}
+
+SCString SCString::left( uint len ) const
+{
+ if ( isEmpty() )
+ {
+ return SCString();
+ }
+ else if ( len >= length() )
+ {
+ return *this;
+ }
+ else
+ {
+ SCString s( len+1 );
+ strncpy( s.data(), m_data, len );
+ *(s.data()+len) = '\0';
+ return s;
+ }
+}
+
+SCString SCString::right( uint len ) const
+{
+ if ( isEmpty() )
+ {
+ return SCString();
+ }
+ else
+ {
+ uint l = length();
+ if ( len > l ) len = l;
+ char *p = m_data + (l - len);
+ return SCString( p );
+ }
+}
+
+SCString SCString::mid( uint index, uint len) const
+{
+ uint slen = length();
+ if ( len == 0xffffffff ) len = slen-index;
+ if ( isEmpty() || index >= slen )
+ {
+ return SCString();
+ }
+ else
+ {
+ register char *p = data()+index;
+ SCString s( len+1 );
+ strncpy( s.data(), p, len );
+ *(s.data()+len) = '\0';
+ return s;
+ }
+}
+
+SCString SCString::lower() const
+{
+ SCString s( m_data );
+ register char *p = s.data();
+ if ( p )
+ {
+ while ( *p )
+ {
+ *p = tolower((uchar) *p);
+ p++;
+ }
+ }
+ return s;
+}
+
+SCString SCString::upper() const
+{
+ SCString s( m_data );
+ register char *p = s.data();
+ if ( p ) {
+ while ( *p ) {
+ *p = toupper((uchar)*p);
+ p++;
+ }
+ }
+ return s;
+}
+
+SCString SCString::stripWhiteSpace() const
+{
+ if ( isEmpty() ) // nothing to do
+ return *this;
+
+ register char *s = m_data;
+ int reslen = length();
+ if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) )
+ return *this; // returns a copy
+
+ SCString result(s);
+ s = result.data();
+ int start = 0;
+ int end = reslen - 1;
+ while ( isspace((uchar) s[start]) ) // skip white space from start
+ start++;
+ if ( s[start] == '\0' )
+ { // only white space
+ return SCString();
+ }
+ while ( end && isspace((uchar) s[end]) ) // skip white space from end
+ end--;
+ end -= start - 1;
+ memmove( result.data(), &s[start], end );
+ result.resize( end + 1 );
+ return result;
+}
+
+SCString SCString::simplifyWhiteSpace() const
+{
+ if ( isEmpty() ) // nothing to do
+ return *this;
+
+ SCString result( length()+1 );
+ char *from = data();
+ char *to = result.data();
+ char *first = to;
+ while ( TRUE )
+ {
+ while ( *from && isspace((uchar) *from) )
+ from++;
+ while ( *from && !isspace((uchar)*from) )
+ *to++ = *from++;
+ if ( *from )
+ *to++ = 0x20; // ' '
+ else
+ break;
+ }
+ if ( to > first && *(to-1) == 0x20 )
+ to--;
+ *to = '\0';
+ result.resize( (int)((long)to - (long)result.data()) + 1 );
+ return result;
+}
+
+SCString &SCString::insert( uint index, const char *s )
+{
+ int len = qstrlen(s);
+ if ( len == 0 )
+ return *this;
+ uint olen = length();
+ int nlen = olen + len;
+ if ( index >= olen ) // insert after end of string
+ {
+ m_data = (char *)realloc(m_data,nlen+index-olen+1);
+ if ( m_data )
+ {
+ memset( m_data+olen, ' ', index-olen );
+ memcpy( m_data+index, s, len+1 );
+ }
+ }
+ else if ( (m_data = (char *)realloc(m_data,nlen+1)) ) // normal insert
+ {
+ memmove( m_data+index+len, m_data+index, olen-index+1 );
+ memcpy( m_data+index, s, len );
+ }
+ return *this;
+}
+
+SCString &SCString::insert( uint index, char c ) // insert char
+{
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ return insert( index, buf );
+}
+
+SCString& SCString::operator+=( const char *str )
+{
+ if ( !str ) return *this; // nothing to append
+ uint len1 = length();
+ uint len2 = qstrlen(str);
+ char *newData = (char *)realloc( m_data, len1 + len2 + 1 );
+ if (newData)
+ {
+ m_data = newData;
+ memcpy( m_data + len1, str, len2 + 1 );
+ }
+ return *this;
+}
+
+SCString &SCString::operator+=( char c )
+{
+ uint len = length();
+ char *newData = (char *)realloc( m_data, length()+2 );
+ if (newData)
+ {
+ m_data = newData;
+ m_data[len] = c;
+ m_data[len+1] = '\0';
+ }
+ return *this;
+}
+
+SCString &SCString::remove( uint index, uint len )
+{
+ uint olen = length();
+ if ( index + len >= olen ) // range problems
+ {
+ if ( index < olen ) // index ok
+ {
+ resize( index+1 );
+ }
+ }
+ else if ( len != 0 )
+ {
+ memmove( m_data+index, m_data+index+len, olen-index-len+1 );
+ resize( olen-len+1 );
+ }
+ return *this;
+}
+
+SCString &SCString::replace( uint index, uint len, const char *s )
+{
+ remove( index, len );
+ insert( index, s );
+ return *this;
+}
+
+SCString &SCString::replace( const QRegExp &rx, const char *str )
+{
+ QString d = QString::fromLatin1( m_data );
+ QString r = QString::fromLatin1( str );
+ d.replace( rx, r );
+ return assign(d.ascii());
+}
+
+long SCString::toLong( bool *ok ) const
+{
+ QString s(m_data);
+ return s.toLong(ok);
+}
+
+ulong SCString::toULong( bool *ok ) const
+{
+ QString s(m_data);
+ return s.toULong(ok);
+}
+
+short SCString::toShort( bool *ok ) const
+{
+ QString s(m_data);
+ return s.toShort(ok);
+}
+
+ushort SCString::toUShort( bool *ok ) const
+{
+ QString s(m_data);
+ return s.toUShort(ok);
+}
+
+int SCString::toInt( bool *ok ) const
+{
+ QString s(m_data);
+ return s.toInt(ok);
+}
+
+uint SCString::toUInt( bool *ok ) const
+{
+ QString s(m_data);
+ return s.toUInt(ok);
+}
+
+SCString &SCString::setNum( long n )
+{
+ char buf[20];
+ register char *p = &buf[19];
+ bool neg;
+ if ( n < 0 )
+ {
+ neg = TRUE;
+ n = -n;
+ }
+ else
+ {
+ neg = FALSE;
+ }
+ *p = '\0';
+ do
+ {
+ *--p = ((int)(n%10)) + '0';
+ n /= 10;
+ } while ( n );
+ if ( neg ) *--p = '-';
+ operator=( p );
+ return *this;
+}
+
+SCString &SCString::setNum( ulong n )
+{
+ char buf[20];
+ register char *p = &buf[19];
+ *p = '\0';
+ do
+ {
+ *--p = ((int)(n%10)) + '0';
+ n /= 10;
+ } while ( n );
+ operator=( p );
+ return *this;
+}
+
+void SCString::msg_index( uint index )
+{
+#if defined(CHECK_RANGE)
+ qWarning( "SCString::at: Absolute index %d out of range", index );
+#else
+ Q_UNUSED( index )
+#endif
+}
+
+bool SCString::stripPrefix(const char *prefix)
+{
+ if (prefix==0) return FALSE;
+ uint plen = qstrlen(prefix);
+ if (m_data && qstrncmp(prefix,m_data,plen)==0) // prefix matches
+ {
+ uint len = qstrlen(m_data);
+ uint newlen = len-plen+1;
+ qmemmove(m_data,m_data+plen,newlen);
+ resize(newlen);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+void *qmemmove( void *dst, const void *src, uint len )
+{
+ register char *d;
+ register char *s;
+ if ( dst > src ) {
+ d = (char *)dst + len - 1;
+ s = (char *)src + len - 1;
+ while ( len-- )
+ *d-- = *s--;
+ } else if ( dst < src ) {
+ d = (char *)dst;
+ s = (char *)src;
+ while ( len-- )
+ *d++ = *s++;
+ }
+ return dst;
+}
+
+char *qstrdup( const char *str )
+{
+ if ( !str )
+ return 0;
+ char *dst = new char[strlen(str)+1];
+ CHECK_PTR( dst );
+ return strcpy( dst, str );
+}
+
+char *qstrncpy( char *dst, const char *src, uint len )
+{
+ if ( !src )
+ return 0;
+ strncpy( dst, src, len );
+ if ( len > 0 )
+ dst[len-1] = '\0';
+ return dst;
+}
+
+int qstricmp( const char *str1, const char *str2 )
+{
+ register const uchar *s1 = (const uchar *)str1;
+ register const uchar *s2 = (const uchar *)str2;
+ int res;
+ uchar c;
+ if ( !s1 || !s2 )
+ return s1 == s2 ? 0 : (int)((long)s2 - (long)s1);
+ for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ )
+ if ( !c ) // strings are equal
+ break;
+ return res;
+}
+
+int qstrnicmp( const char *str1, const char *str2, uint len )
+{
+ register const uchar *s1 = (const uchar *)str1;
+ register const uchar *s2 = (const uchar *)str2;
+ int res;
+ uchar c;
+ if ( !s1 || !s2 )
+ return (int)((long)s2 - (long)s1);
+ for ( ; len--; s1++, s2++ ) {
+ if ( (res = (c=tolower(*s1)) - tolower(*s2)) )
+ return res;
+ if ( !c ) // strings are equal
+ break;
+ }
+ return 0;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+QDataStream &operator<<( QDataStream &s, const QByteArray &a )
+{
+ return s.writeBytes( a.data(), a.size() );
+}
+
+QDataStream &operator>>( QDataStream &s, QByteArray &a )
+{
+ Q_UINT32 len;
+ s >> len; // read size of array
+ if ( len == 0 || s.eof() ) { // end of file reached
+ a.resize( 0 );
+ return s;
+ }
+ if ( !a.resize( (uint)len ) ) { // resize array
+#if defined(CHECK_NULL)
+ qWarning( "QDataStream: Not enough memory to read QByteArray" );
+#endif
+ len = 0;
+ }
+ if ( len > 0 ) // not null array
+ s.readRawBytes( a.data(), (uint)len );
+ return s;
+}
+
+QDataStream &operator<<( QDataStream &s, const SCString &str )
+{
+ return s.writeBytes( str.data(), str.size() );
+}
+
+QDataStream &operator>>( QDataStream &s, SCString &str )
+{
+ Q_UINT32 len;
+ s >> len; // read size of string
+ if ( len == 0 || s.eof() ) { // end of file reached
+ str.resize( 0 );
+ return s;
+ }
+ if ( !str.resize( (uint)len )) {// resize string
+#if defined(CHECK_NULL)
+ qWarning( "QDataStream: Not enough memory to read QCString" );
+#endif
+ len = 0;
+ }
+ if ( len > 0 ) // not null array
+ s.readRawBytes( str.data(), (uint)len );
+ return s;
+}
+
+#endif //QT_NO_DATASTREAM
+
+
+
+#endif
diff --git a/qtools/scstring.h b/qtools/scstring.h
new file mode 100644
index 0000000..a9b462c
--- /dev/null
+++ b/qtools/scstring.h
@@ -0,0 +1,155 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2004 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#ifndef SCSTRING_H
+#define SCSTRING_H
+
+#include <stdlib.h>
+
+class QRegExp;
+
+/** This is an alternative implementation of QCString. It provides basically
+ * the same functions but uses less memory for administration. This class
+ * is just a wrapper around a plain C string requiring only 4 bytes "overhead".
+ * QCString features sharing of data and stores the string length, but
+ * requires 4 + 12 bytes for this (even for the empty string). As doxygen
+ * uses a LOT of string during a run it saves a lot of memory to use a
+ * more memory efficient implementation at the cost of relatively low
+ * runtime overhead.
+ */
+class SCString
+{
+public:
+ SCString() : m_data(0) {} // make null string
+ SCString( const SCString &s );
+ SCString( int size );
+ SCString( const char *str );
+ SCString( const char *str, uint maxlen );
+ ~SCString();
+
+ SCString &operator=( const SCString &s );// deep copy
+ SCString &operator=( const char *str ); // deep copy
+
+ bool isNull() const;
+ bool isEmpty() const;
+ uint length() const;
+ uint size() const { return m_data ? length()+1 : 0; }
+ char * data() const { return m_data; }
+ bool resize( uint newlen );
+ bool truncate( uint pos );
+ bool fill( char c, int len = -1 );
+
+ SCString copy() const;
+
+ SCString &sprintf( const char *format, ... );
+
+ int find( char c, int index=0, bool cs=TRUE ) const;
+ int find( const char *str, int index=0, bool cs=TRUE ) const;
+ int find( const QRegExp &, int index=0 ) const;
+ int find( const QCString &str, int index, bool cs ) const;
+ int findRev( char c, int index=-1, bool cs=TRUE) const;
+ int findRev( const char *str, int index=-1, bool cs=TRUE) const;
+ int findRev( const QRegExp &, int index=-1 ) const;
+ int contains( char c, bool cs=TRUE ) const;
+ int contains( const char *str, bool cs=TRUE ) const;
+ int contains( const QRegExp & ) const;
+ bool stripPrefix(const char *prefix);
+
+ SCString left( uint len ) const;
+ SCString right( uint len ) const;
+ SCString mid( uint index, uint len=0xffffffff) const;
+
+ SCString lower() const;
+ SCString upper() const;
+
+ SCString stripWhiteSpace() const;
+ SCString simplifyWhiteSpace() const;
+
+ SCString &assign( const char *str );
+ SCString &insert( uint index, const char * );
+ SCString &insert( uint index, char );
+ SCString &append( const char *s );
+ SCString &prepend( const char *s );
+ SCString &remove( uint index, uint len );
+ SCString &replace( uint index, uint len, const char * );
+ SCString &replace( const QRegExp &, const char * );
+
+ short toShort( bool *ok=0 ) const;
+ ushort toUShort( bool *ok=0 ) const;
+ int toInt( bool *ok=0 ) const;
+ uint toUInt( bool *ok=0 ) const;
+ long toLong( bool *ok=0 ) const;
+ ulong toULong( bool *ok=0 ) const;
+
+ SCString &setNum( short );
+ SCString &setNum( ushort );
+ SCString &setNum( int );
+ SCString &setNum( uint );
+ SCString &setNum( long );
+ SCString &setNum( ulong );
+ QCString &setNum( float, char f='g', int prec=6 );
+ QCString &setNum( double, char f='g', int prec=6 );
+
+ operator const char *() const;
+ SCString &operator+=( const char *str );
+ SCString &operator+=( char c );
+ char &at( uint index ) const;
+ char &operator[]( int i ) const { return at(i); }
+
+ private:
+ static void msg_index( uint );
+ void duplicate( const SCString &s );
+ void duplicate( const char *str);
+ SCString &duplicate( const char *str, int);
+
+ char * m_data;
+};
+
+inline char &SCString::at( uint index ) const
+{
+ return m_data[index];
+}
+
+inline void SCString::duplicate( const SCString &s )
+{
+ if (!s.isEmpty())
+ {
+ uint l = strlen(s.data());
+ m_data = (char *)malloc(l+1);
+ if (m_data) memcpy(m_data,s.data(),l+1);
+ }
+ else
+ m_data=0;
+}
+inline void SCString::duplicate( const char *str)
+{
+ if (str && str[0]!='\0')
+ {
+ uint l = strlen(str);
+ m_data = (char *)malloc(l+1);
+ if (m_data) memcpy(m_data,str,l+1);
+ }
+ else
+ m_data=0;
+}
+inline SCString &SCString::duplicate( const char *str, int)
+{
+ if (m_data) free(m_data);
+ duplicate(str);
+ return *this;
+}
+
+#endif
+