summaryrefslogtreecommitdiffstats
path: root/qtools
diff options
context:
space:
mode:
authorDimitri van Heesch <doxygen@gmail.com>2020-06-07 09:36:24 (GMT)
committerDimitri van Heesch <doxygen@gmail.com>2020-06-10 18:36:25 (GMT)
commit1fa64cc88d0400eccb85fe4a687a269870fc3017 (patch)
tree32f21f1e5e6540e7729b0b21698c3fe89a94bcbf /qtools
parent95f9c89d6aa0008321c2ee8a0f3b1a4602789395 (diff)
downloadDoxygen-1fa64cc88d0400eccb85fe4a687a269870fc3017.zip
Doxygen-1fa64cc88d0400eccb85fe4a687a269870fc3017.tar.gz
Doxygen-1fa64cc88d0400eccb85fe4a687a269870fc3017.tar.bz2
Refactor: make QCString a wrapper around std::string
Diffstat (limited to 'qtools')
-rw-r--r--qtools/qcstring.cpp273
-rw-r--r--qtools/qcstring.h806
2 files changed, 254 insertions, 825 deletions
diff --git a/qtools/qcstring.cpp b/qtools/qcstring.cpp
index 8d442d7..8169979 100644
--- a/qtools/qcstring.cpp
+++ b/qtools/qcstring.cpp
@@ -218,135 +218,6 @@ int QCString::contains( const QRegExp &rx ) const
return count;
}
-bool QCString::startsWith( const char *s ) const
-{
- const char *p = data();
- if (p==0 || s==0) return s==0;
- while (*p!=0 && *p==*s) p++,s++;
- return *s==0;
-}
-
-bool QCString::stripPrefix(const char *prefix)
-{
- if (prefix==0 || length()==0) return FALSE;
- int len = qstrlen(prefix);
- if (qstrncmp(prefix,data(),len)==0)
- {
- m_rep=mid(len,length()-len).m_rep; // need to make a deep copy
- return TRUE;
- }
- return FALSE;
-}
-
-QCString QCString::left( uint len ) const
-{
- if (isEmpty())
- {
- return QCString();
- }
- else if (len>=length())
- {
- return QCString(data());
- }
- else
- {
- QCString s( len+1 );
- memcpy( s.rawData(), data(), len);
- return s;
- }
-}
-
-QCString QCString::right( uint len ) const
-{
- if (isEmpty())
- {
- return QCString();
- }
- else
- {
- int l = length();
- if ((int)len>l) len=l;
- const char *pos = data() + (l-len);
- return QCString(pos);
- }
-}
-
-QCString QCString::mid( uint index, uint len) const
-{
- uint slen = (uint)length();
- if (len==0xffffffff) len = slen-index;
- if (isEmpty() || index>=slen || len==0)
- {
- return QCString();
- }
- else
- {
- const char *p = data()+index;
- QCString s(len+1);
- qstrncpy( s.rawData(), p, len+1 );
- return s;
- }
-}
-
-QCString QCString::lower() const
-{
- if (length()==0) return QCString();
- QCString s(data());
- char *pos = s.rawData();
- if (pos)
- {
- while (*pos)
- {
- *pos = tolower((unsigned char)*pos);
- pos++;
- }
- }
- return s;
-}
-
-QCString QCString::upper() const
-{
- if (length()==0) return QCString();
- QCString s(data());
- char *pos = s.rawData();
- if (pos)
- {
- while (*pos)
- {
- *pos = toupper((unsigned char)*pos);
- pos++;
- }
- }
- return s;
-}
-
-QCString QCString::stripWhiteSpace() const
-{
- if ( isEmpty() ) // nothing to do
- return *this;
-
- const char *cs = data();
- int reslen = length();
- if ( !isspace((uchar)cs[0]) && !isspace((uchar)cs[reslen-1]) )
- return *this; // returns a copy
-
- QCString result(cs);
- char *s = result.rawData();
- 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 QCString();
- }
- while ( end && isspace((uchar) s[end]) ) // skip white space from end
- end--;
- end -= start - 1;
- qmemmove( s, &s[start], end );
- result.resize( end + 1 );
- return result;
-}
QCString QCString::simplifyWhiteSpace() const
{
@@ -375,67 +246,6 @@ 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(rawData()+olen, ' ', index-olen);
- memcpy(rawData()+index,s, len+1);
- }
- else
- {
- resize(nlen+1);
- qmemmove(rawData()+index+len,data()+index,olen-index+1);
- memcpy(rawData()+index,s,len);
- }
- return *this;
-}
-
-QCString &QCString::insert( uint index, char c)
-{
- char buf[2];
- buf[0] = c;
- buf[1] = '\0';
- return insert( index, buf );
-}
-QCString &QCString::append( const char *s )
-{
- return operator+=(s);
-}
-QCString &QCString::prepend( const char *s )
-{
- return insert(0,s);
-}
-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 )
- {
- QCString tmp(olen-index-len+1);
- qmemmove( tmp.rawData(), data()+index+len, olen-index-len+1 );
- resize( olen-len+1 );
- memcpy( rawData()+index,tmp.data(),tmp.length() );
- }
- return *this;
-}
-
QCString &QCString::replace( uint index, uint len, const char *s)
{
remove( index, len );
@@ -645,65 +455,6 @@ bye:
return is_ok ? val : 0;
}
-QCString &QCString::setNum(short n)
-{
- return setNum((long)n);
-}
-
-QCString &QCString::setNum(ushort n)
-{
- return setNum((ulong)n);
-}
-
-QCString &QCString::setNum(int n)
-{
- return setNum((long)n);
-}
-
-QCString &QCString::setNum(uint n)
-{
- return setNum((ulong)n);
-}
-
-QCString &QCString::setNum(long n)
-{
- char buf[20];
- 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;
-}
-
-QCString &QCString::setNum( ulong n)
-{
- char buf[20];
- char *p = &buf[19];
- *p = '\0';
- do
- {
- *--p = ((int)(n%10)) + '0';
- n /= 10;
- } while ( n );
- operator=( p );
- return *this;
-}
-
//-------------------------------------------------
void *qmemmove( void *dst, const void *src, uint len )
@@ -828,16 +579,12 @@ QDataStream &operator>>( QDataStream &s, QCString &str )
inline QCString operator+( const QCString &s1, const QGString &s2 )
{
- QCString tmp(s1);
- tmp += s2.data();
- return tmp;
+ return s1.str()+s2.data();
}
inline QCString operator+( const QGString &s1, const QCString &s2 )
{
- QCString tmp(s1.data());
- tmp += s2;
- return tmp;
+ return s1.data()+s2.str();
}
/// substitute all occurrences of \a src in \a s by \a dst
@@ -934,19 +681,3 @@ QCString substitute(const QCString &s,const QCString &src,const QCString &dst,in
return result;
}
-/// substitute all occurrences of \a srcChar in \a s by \a dstChar
-QCString substitute(const QCString &s,char srcChar,char dstChar)
-{
- int l=s.length();
- QCString result(l+1);
- char *q=result.rawData();
- if (l>0)
- {
- const char *p=s.data();
- char c;
- while ((c=*p++)) *q++ = (c==srcChar) ? dstChar : c;
- }
- *q='\0';
- return result;
-}
-
diff --git a/qtools/qcstring.h b/qtools/qcstring.h
index b126194..9c10bec 100644
--- a/qtools/qcstring.h
+++ b/qtools/qcstring.h
@@ -22,52 +22,21 @@
#endif // QT_H
#include <string>
+#include <algorithm>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if !defined(_OS_WIN32_) || defined(__MINGW32__)
-#include <stdint.h>
-#endif
-
-#if defined(_OS_SUN_) && defined(_CC_GNU_)
-#include <strings.h>
-#endif
-
-#include <assert.h>
+#include <cctype>
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include <cstdint>
class QGString;
/*****************************************************************************
- Fixes and workarounds for some platforms
- *****************************************************************************/
-
-#if defined(_OS_HPUX_)
-// HP-UX has badly defined strstr() etc.
-// ### fix in 3.0: change hack_* to qt_hack_*
-// by the way HP-UX is probably right, the standard has evolved and
-// we'll have to adapt to it
-inline char *hack_strstr( const char *s1, const char *s2 )
-{ return (char *)strstr(s1, s2); }
-inline char *hack_strchr( const char *s, int c )
-{ return (char *)strchr(s, c); }
-inline char *hack_strrchr( const char *s, int c )
-{ return (char *)strrchr(s, c); }
-#define strstr(s1,s2) hack_strstr((s1),(s2))
-#define strchr(s,c) hack_strchr((s),(c))
-#define strrchr(s,c) hack_strrchr((s),(c))
-#endif
-
-/*****************************************************************************
Safe and portable C string functions; extensions to standard string.h
*****************************************************************************/
-Q_EXPORT void *qmemmove( void *dst, const void *src, uint len );
-
-#if defined(_OS_SUN_) || defined(_CC_OC_)
-#define memmove(s1,s2,n) qmemmove((s1),(s2),(n))
-#endif
+void *qmemmove( void *dst, const void *src, uint len );
#if defined(_OS_WIN32_)
#define qsnprintf _snprintf
@@ -75,45 +44,45 @@ Q_EXPORT void *qmemmove( void *dst, const void *src, uint len );
#define qsnprintf snprintf
#endif
-Q_EXPORT char *qstrdup( const char * );
+char *qstrdup( const char * );
-Q_EXPORT inline uint cstrlen( const char *str )
+inline uint cstrlen( const char *str )
{ return (uint)strlen(str); }
-Q_EXPORT inline uint qstrlen( const char *str )
+inline uint qstrlen( const char *str )
{ return str ? (uint)strlen(str) : 0; }
-Q_EXPORT inline char *cstrcpy( char *dst, const char *src )
+inline char *cstrcpy( char *dst, const char *src )
{ return strcpy(dst,src); }
-Q_EXPORT inline char *qstrcpy( char *dst, const char *src )
+inline char *qstrcpy( char *dst, const char *src )
{ return src ? strcpy(dst, src) : 0; }
-Q_EXPORT char * qstrncpy(char *src,const char *dst, uint len);
+char * qstrncpy(char *src,const char *dst, uint len);
-Q_EXPORT inline int cstrcmp( const char *str1, const char *str2 )
+inline int cstrcmp( const char *str1, const char *str2 )
{ return strcmp(str1,str2); }
-Q_EXPORT inline int qstrcmp( const char *str1, const char *str2 )
+inline int qstrcmp( const char *str1, const char *str2 )
{ return (str1 && str2) ? strcmp(str1,str2) : (int)((intptr_t)str2 - (intptr_t)str1); }
-Q_EXPORT inline int cstrncmp( const char *str1, const char *str2, uint len )
+inline int cstrncmp( const char *str1, const char *str2, uint len )
{ return strncmp(str1,str2,len); }
-Q_EXPORT inline int qstrncmp( const char *str1, const char *str2, uint len )
+inline int qstrncmp( const char *str1, const char *str2, uint len )
{ return (str1 && str2) ? strncmp(str1,str2,len) :
(int)((intptr_t)str2 - (intptr_t)str1); }
-Q_EXPORT int qstricmp( const char *str1, const char *str2 );
+int qstricmp( const char *str1, const char *str2 );
-Q_EXPORT int qstrnicmp( const char *str1, const char *str2, uint len );
+int qstrnicmp( const char *str1, const char *str2, uint len );
/*****************************************************************************
QByteArray class
*****************************************************************************/
#if defined(Q_TEMPLATEDLL)
-template class Q_EXPORT QArray<char>;
+template class QArray<char>;
#endif
typedef QArray<char> QByteArray;
@@ -121,120 +90,75 @@ typedef QArray<char> QByteArray;
QByteArray stream functions
*****************************************************************************/
#ifndef QT_NO_DATASTREAM
-Q_EXPORT QDataStream &operator<<( QDataStream &, const QByteArray & );
-Q_EXPORT QDataStream &operator>>( QDataStream &, QByteArray & );
+QDataStream &operator<<( QDataStream &, const QByteArray & );
+QDataStream &operator>>( QDataStream &, QByteArray & );
#endif
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 std::string as the underlying string type
*/
class QCString
{
-public:
- /** creates an empty string */
- QCString() : m_rep()
- {
- }
-
- /** destroys the string */
- ~QCString()
- {
- }
+ public:
+ QCString() = default;
+ ~QCString() = default;
+ QCString( const QCString &s ) = default;
+ QCString &operator=( const QCString &s ) = default;
+ QCString( QCString &&s ) = default;
+ QCString &operator=( QCString &&s ) = default;
- /** makes a copy of a string. */
- QCString( const QCString &s ) : m_rep(s.m_rep)
- {
- }
+ QCString( const std::string &s ) : m_rep(s) {}
/** creates a string with room for size characters
- * @param[in] size the number of character to allocate (including the 0-terminator)
+ * @param[in] size the number of character to allocate (also counting the 0-terminator!)
*/
- explicit QCString( uint size ) : m_rep(size)
- {
- }
+ explicit QCString( uint size ) { m_rep.resize(size>0 ? size-1 : 0); }
/** 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)
- {
- }
+ QCString( const char *str ) : m_rep(str?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)
- {
- }
+ QCString( const char *str, uint maxlen ) : m_rep(str?str:"") { m_rep.resize(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;
- }
+ QCString &operator=( const char *str) { m_rep = str?str:""; return *this; }
/** Returns TRUE iff the string is empty. Equivalent to isEmpty(). */
- bool isNull() const
- {
- return m_rep.isEmpty();
- }
+ bool isNull() const { return m_rep.empty(); }
/** Returns TRUE iff the string is empty */
- bool isEmpty() const
- {
- return m_rep.isEmpty();
- }
+ bool isEmpty() const { return m_rep.empty(); }
- /** 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, not counting the 0-terminator. Equivalent to size(). */
+ uint length() const { return (uint)m_rep.size(); }
- /** Returns the length of the string, excluding the 0-terminator. */
- uint size() const
- {
- return m_rep.length();
- }
+ /** Returns the length of the string, not counting the 0-terminator. */
+ uint size() const { return (uint)m_rep.size(); }
/** Returns a pointer to the contents of the string in the form of a 0-terminated C string */
- const char *data() const
- {
- return m_rep.data();
- }
+ const char *data() const { return m_rep.empty() ? 0 : m_rep.c_str(); }
/** Returns a writable pointer to the data.
* @warning if the string is shared it will modifying the string directly and
* this will overwrite all copies as well!
*/
- char *rawData() const
- {
- return m_rep.rawData();
- }
+ char *rawData() const { return m_rep.empty() ? 0 : const_cast<char*>(&m_rep[0]); }
/** Resizes the string to hold \a newlen characters
- * (this value should include the 0-terminator). If the string is enlarged the contents will
+ * (this value should also count the 0-terminator).
+ * If the string is enlarged the contents will
* be left unmodified.
*/
- bool resize( uint newlen )
- {
- m_rep.resize(newlen);
- return TRUE;
- }
+ bool resize( uint newlen ) { m_rep.resize( newlen>0 ? newlen-1 : 0 ); return TRUE; }
/** Truncates the string at position \a pos. */
- bool truncate( uint pos )
- {
- return resize(pos+1);
- }
+ 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.
@@ -244,523 +168,286 @@ public:
*/
bool fill( char c, int len = -1 )
{
- m_rep.fill(c,len);
+ int l = len==-1 ? m_rep.size() : len;
+ m_rep = std::string(l,c);
return TRUE;
}
/** Returns a deep copy of the string. */
- QCString copy() const
- {
- if (length()==0) return QCString();
- QCString cs(length()+1);
- memcpy(cs.rawData(),data(),length());
- return cs;
- }
+ QCString copy() const { return *this; }
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=(uint)-1) const;
- QCString lower() const;
- QCString upper() const;
- QCString stripWhiteSpace() const;
+
+ bool stripPrefix(const char *prefix)
+ {
+ if (prefix==0 || m_rep.empty()) return FALSE;
+ if (m_rep.rfind(prefix,0)==0) // string starts with prefix
+ {
+ m_rep.erase(0,qstrlen(prefix));
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ QCString left( uint len ) const
+ {
+ return m_rep.empty() ? QCString() : QCString(m_rep.substr(0,len));
+ }
+
+ QCString right( uint len ) const
+ {
+ return m_rep.empty() ? QCString() :
+ len<m_rep.size() ? QCString(m_rep.substr(m_rep.size()-len,len)) :
+ *this;
+ }
+
+ QCString mid( uint index, uint len=(uint)-1) const
+ {
+ uint slen = (uint)m_rep.size();
+ if (len==(uint)-1) len = slen-index;
+ return m_rep.empty() || index>slen || len==0 ? QCString() :
+ QCString(m_rep.substr(index,len));
+ }
+
+ QCString lower() const
+ {
+ std::string s = m_rep;
+ std::transform(s.begin(),s.end(),s.begin(),
+ [](unsigned char c){ return std::tolower(c); });
+ return s;
+ }
+
+ QCString upper() const
+ {
+ std::string s = m_rep;
+ std::transform(s.begin(),s.end(),s.begin(),
+ [](unsigned char c){ return std::toupper(c); });
+ return s;
+ }
+
+ QCString stripWhiteSpace() const
+ {
+ int sl = (uint)m_rep.size();
+ if (sl==0 || (!std::isspace(m_rep[0]) && !std::isspace(m_rep[sl-1]))) return *this;
+ int start=0,end=sl-1;
+ while (start<sl && std::isspace(m_rep[start])) start++;
+ if (start==sl) return QCString(); // only whitespace
+ while (end>start && std::isspace(m_rep[end])) end--;
+ return QCString(m_rep.substr(start,1+end-start));
+ }
+
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 &insert( uint index, const char *s )
+ {
+ uint len = s ? qstrlen(s) : 0;
+ if (len>0)
+ {
+ uint ol = m_rep.size();
+ if (index>ol) // insert beyond end of string and fill gap with spaces
+ {
+ m_rep.resize(index+len);
+ std::memset(&m_rep[ol],' ',index-ol);
+ std::memcpy(&m_rep[index],s,len+1);
+ }
+ else // insert inside the string
+ {
+ m_rep.insert(index,s);
+ }
+ }
+ return *this;
+ }
+
+ QCString &insert( uint index, char c)
+ {
+ char s[2] = { c, '\0' };
+ return insert(index,s);
+ }
+
+ QCString &append( const char *s )
+ {
+ return operator+=(s);
+ }
+
+ QCString &prepend( const char *s )
+ {
+ return insert(0,s);
+ }
+
+ QCString &remove( uint index, uint len )
+ {
+ uint ol = (uint)m_rep.size();
+ if (index<ol && len>0) m_rep.erase(index,index+len>=ol ? std::string::npos : len);
+ return *this;
+ }
+
QCString &replace( uint index, uint len, const char *s);
QCString &replace( const QRegExp &rx, const char *str );
- short toShort( bool *ok=0, int base=10 ) const;
+
+ short toShort( bool *ok=0, int base=10 ) const;
ushort toUShort( bool *ok=0, int base=10 ) const;
- int toInt( bool *ok=0, int base=10 ) const;
- uint toUInt( bool *ok=0, int base=10 ) const;
- long toLong( bool *ok=0, int base=10 ) const;
- ulong toULong( bool *ok=0, int base=10 ) const;
+ int toInt( bool *ok=0, int base=10 ) const;
+ uint toUInt( bool *ok=0, int base=10 ) const;
+ long toLong( bool *ok=0, int base=10 ) const;
+ ulong toULong( bool *ok=0, int base=10 ) const;
uint64 toUInt64( bool *ok=0, int base=10 ) 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);
- bool startsWith( const char *s ) const;
- /** Converts the string to a plain C string */
- operator const char *() const
+ QCString &setNum(short n)
{
- return (const char *)data();
+ m_rep = std::to_string(n);
+ return *this;
}
- /** Appends string \a str to this string and returns a reference to the result. */
- QCString &operator+=( const char *str )
+ QCString &setNum(ushort n)
{
- if (!str) return *this;
- uint len1 = length();
- uint len2 = (uint)strlen(str);
- resize(len1+len2+1);
- memcpy(rawData()+len1,str,len2);
+ m_rep = std::to_string(n);
return *this;
}
- /** Appends character \a c to this string and returns a reference to the result. */
- QCString &operator+=( char c )
+ QCString &setNum(int n)
{
- uint len = length();
- resize(len+2);
- rawData()[len]=c;
+ m_rep = std::to_string(n);
return *this;
}
- /** Returns a reference to the character at index \a i. */
- char &at( uint i) const
+ QCString &setNum(uint n)
{
- return m_rep.at(i);
+ m_rep = std::to_string(n);
+ return *this;
}
- /** Indexing operator. Equivalent to at(). */
- char &operator[]( int i ) const
+ QCString &setNum(long n)
{
- return m_rep.at((uint)i);
+ m_rep = std::to_string(n);
+ return *this;
}
- private:
-
- struct LSData;
-
- // long string representation
- struct LongStringRep
+ QCString &setNum(ulong n)
{
- uchar isShort; // : 1; // should be shared with ShortStringRep
- //uchar : 7;
- LSData *d;
- };
+ m_rep = std::to_string(n);
+ return *this;
+ }
-#define SHORT_STR_CAPACITY ((int)sizeof(LongStringRep)-2)
-#define SHORT_STR_MAX_LEN (SHORT_STR_CAPACITY-1)
+ bool startsWith( const char *s ) const
+ {
+ if (m_rep.empty() || s==0) return s==0;
+ return m_rep.rfind(s,0)==0; // looking "backward" starting and ending at index 0
+ }
- // short string representation
- struct ShortStringRep
+ /** Converts the string to a plain C string */
+ operator const char *() const
{
- uchar isShort; // : 1; // should be shared with LongStringRep
- uchar len; // : 7;
- char str[SHORT_STR_CAPACITY]; // size including 0-terminator
- };
+ return const_cast<const char *>(data());
+ }
- // ref counting string header
- struct LSHeader
+ std::string str() const
{
- uint 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
+ return m_rep;
+ }
+
+ /** Appends string \a str to this string and returns a reference to the result. */
+ QCString &operator+=( const char *str )
{
- char *toStr()
- {
- return (char*)(this+1); // string data starts after the header
- }
+ if (str) m_rep+=str;
+ return *this;
+ }
- // 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(uint 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);
- }
+ /** Appends character \a c to this string and returns a reference to the result. */
+ QCString &operator+=( char c )
+ {
+ m_rep+=c;
+ return *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,uint 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);
- uint len = d->len;
- if (len>=size) len=size-1;
- memcpy(newData->toStr(),d->toStr(),len);
- newData->toStr()[len]=0;
- d->dispose();
- return newData;
- }
- }
- };
+ /** Returns a reference to the character at index \a i. */
+ char &at( uint i) const
+ {
+ return const_cast<char&>(m_rep[i]);
+ }
- class StringRep
+ /** Indexing operator. Equivalent to at(). */
+ char &operator[]( int i ) const
{
- public:
- StringRep()
- {
- initEmpty();
- }
- void initEmpty()
- {
- u.s.isShort=TRUE;
- u.s.len=0;
- //memset(u.s.str,0,SHORT_STR_CAPACITY);
- }
- ~StringRep()
- {
- if (!u.s.isShort)
- {
- u.l.d->dispose();
- }
- }
- StringRep(const StringRep &s)
- {
- if (&s!=this)
- {
- u.s.isShort = s.u.s.isShort;
- if (s.u.s.isShort)
- {
- u.s.len = s.u.s.len;
- memcpy(u.s.str,s.u.s.str,s.u.s.len+1);
- }
- else
- {
- u.l.d = s.u.l.d;
- u.l.d->refCount++;
- }
- }
- else // self-assignment
- {
- u = s.u; // avoid uninitialized warning from gcc
- }
- }
- StringRep(uint size)
- {
- u.s.isShort = size<=SHORT_STR_CAPACITY;
- if (size<=SHORT_STR_CAPACITY) // init short string
- {
- if (size>0)
- {
- u.s.len = (uchar)(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)
- {
- uint len = (uint)strlen(str);
- u.s.isShort = len<SHORT_STR_CAPACITY;
- if (len<SHORT_STR_CAPACITY)
- {
- u.s.len = (uchar)len;
- qstrncpy(u.s.str,str,SHORT_STR_CAPACITY);
- }
- else
- {
- u.l.d = LSData::create(len+1);
- memcpy(u.l.d->toStr(),str,u.l.d->len);
- }
- }
- else // create empty string
- {
- initEmpty();
- }
- }
- StringRep( const char *str, uint maxlen )
- {
- if (str && maxlen>0)
- {
- uint len=(uint)strlen(str);
- if (len>maxlen) len=maxlen;
- u.s.isShort = len<=SHORT_STR_MAX_LEN;
- if (u.s.isShort)
- {
- u.s.len = (uchar)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
- {
- initEmpty();
- }
- }
- StringRep &operator=(const StringRep &s)
- {
- if (&s!=this)
- {
- if (!u.s.isShort)
- {
- u.l.d->dispose();
- }
- u.s.isShort = s.u.s.isShort;
- if (u.s.isShort) // copy by value
- {
- u.s.len = s.u.s.len;
- memcpy(u.s.str,s.u.s.str,s.u.s.len+1);
- }
- else // copy by reference
- {
- u.l.d = s.u.l.d;
- u.l.d->refCount++;
- }
- }
- else // self-assignment
- {
- u = s.u; // avoid uninitialized warning from gcc
- }
- return *this;
- }
- StringRep &operator=(const char *str)
- {
- if (!u.s.isShort)
- {
- u.l.d->dispose();
- }
- if (str)
- {
- uint len = (uint)strlen(str);
- u.s.isShort = len<SHORT_STR_CAPACITY;
- if (len<SHORT_STR_CAPACITY)
- {
- u.s.len = (uchar)len;
- qstrncpy(u.s.str,str,SHORT_STR_CAPACITY);
- }
- else
- {
- u.l.d = LSData::create(len+1);
- memcpy(u.l.d->toStr(),str,len);
- }
- }
- else
- {
- initEmpty();
- }
- return *this;
- }
- bool isEmpty() const
- {
- return u.s.isShort && u.s.len==0;
- }
- uint length() const
- {
- uint l = u.s.isShort ? u.s.len : u.l.d->len;
- return l;
- }
- const char *data() const
- {
- if (u.s.isShort)
- {
- return u.s.len==0 ? 0 : u.s.str;
- }
- else
- {
- return u.l.d->len==0 ? 0 : u.l.d->toStr();
- }
- }
- char *rawData() const
- {
- if (u.s.isShort)
- {
- return u.s.len==0 ? 0 : (char*)u.s.str;
- }
- else
- {
- //assert(u.l.d->refCount==0); // string may not be shared when accessed raw
- return u.l.d->len==0 ? 0 : u.l.d->toStr();
- }
- }
- char &at(uint 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 = (uchar)(newlen-1);
- u.s.str[newlen-1]='\0';
- }
- else // string becomes empty
- {
- initEmpty();
- }
- }
- 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();
- initEmpty();
- }
- }
- else // resize long string
- {
- u.l.d = u.l.d->resize(u.l.d,newlen);
- }
- return TRUE;
- }
- bool fill( char c, int len )
- {
- uint ulen = len<0 ? length() : (uint)len;
- if (!u.s.isShort) // detach from shared string
- {
- resize(ulen+1);
- }
- else if (ulen!=length())
- {
- if (ulen>0)
- {
- resize(ulen+1);
- }
- }
- if (ulen>0)
- {
- memset(rawData(),c,ulen);
- }
- return TRUE;
- }
- private:
- union ShortOrLongStringSelector
- {
- ShortStringRep s;
- LongStringRep l;
- } u;
- };
- StringRep m_rep;
+ return const_cast<char&>(m_rep[i]);
+ }
+ private:
+ std::string m_rep;
};
/*****************************************************************************
QCString stream functions
*****************************************************************************/
#ifndef QT_NO_DATASTREAM
-Q_EXPORT QDataStream &operator<<( QDataStream &, const QCString & );
-Q_EXPORT QDataStream &operator>>( QDataStream &, QCString & );
+QDataStream &operator<<( QDataStream &, const QCString & );
+QDataStream &operator>>( QDataStream &, QCString & );
#endif
/*****************************************************************************
QCString non-member operators
*****************************************************************************/
-Q_EXPORT inline bool operator==( const QCString &s1, const QCString &s2 )
+inline bool operator==( const QCString &s1, const QCString &s2 )
{ return qstrcmp(s1.data(),s2.data()) == 0; }
-Q_EXPORT inline bool operator==( const QCString &s1, const char *s2 )
+inline bool operator==( const QCString &s1, const char *s2 )
{ return qstrcmp(s1.data(),s2) == 0; }
-Q_EXPORT inline bool operator==( const char *s1, const QCString &s2 )
+inline bool operator==( const char *s1, const QCString &s2 )
{ return qstrcmp(s1,s2.data()) == 0; }
-Q_EXPORT inline bool operator!=( const QCString &s1, const QCString &s2 )
+inline bool operator!=( const QCString &s1, const QCString &s2 )
{ return qstrcmp(s1.data(),s2.data()) != 0; }
-Q_EXPORT inline bool operator!=( const QCString &s1, const char *s2 )
+inline bool operator!=( const QCString &s1, const char *s2 )
{ return qstrcmp(s1.data(),s2) != 0; }
-Q_EXPORT inline bool operator!=( const char *s1, const QCString &s2 )
+inline bool operator!=( const char *s1, const QCString &s2 )
{ return qstrcmp(s1,s2.data()) != 0; }
-Q_EXPORT inline bool operator<( const QCString &s1, const QCString& s2 )
+inline bool operator<( const QCString &s1, const QCString& s2 )
{ return qstrcmp(s1.data(),s2.data()) < 0; }
-Q_EXPORT inline bool operator<( const QCString &s1, const char *s2 )
+inline bool operator<( const QCString &s1, const char *s2 )
{ return qstrcmp(s1.data(),s2) < 0; }
-Q_EXPORT inline bool operator<( const char *s1, const QCString &s2 )
+inline bool operator<( const char *s1, const QCString &s2 )
{ return qstrcmp(s1,s2.data()) < 0; }
-Q_EXPORT inline bool operator<=( const QCString &s1, const char *s2 )
+inline bool operator<=( const QCString &s1, const char *s2 )
{ return qstrcmp(s1.data(),s2) <= 0; }
-Q_EXPORT inline bool operator<=( const char *s1, const QCString &s2 )
+inline bool operator<=( const char *s1, const QCString &s2 )
{ return qstrcmp(s1,s2.data()) <= 0; }
-Q_EXPORT inline bool operator>( const QCString &s1, const char *s2 )
+inline bool operator>( const QCString &s1, const char *s2 )
{ return qstrcmp(s1.data(),s2) > 0; }
-Q_EXPORT inline bool operator>( const char *s1, const QCString &s2 )
+inline bool operator>( const char *s1, const QCString &s2 )
{ return qstrcmp(s1,s2.data()) > 0; }
-Q_EXPORT inline bool operator>=( const QCString &s1, const char *s2 )
+inline bool operator>=( const QCString &s1, const char *s2 )
{ return qstrcmp(s1.data(),s2) >= 0; }
-Q_EXPORT inline bool operator>=( const char *s1, const QCString &s2 )
+inline bool operator>=( const char *s1, const QCString &s2 )
{ return qstrcmp(s1,s2.data()) >= 0; }
-Q_EXPORT inline QCString operator+( const QCString &s1, const QCString &s2 )
+inline QCString operator+( const QCString &s1, const QCString &s2 )
{
- QCString tmp(s1);
- tmp += s2;
- return tmp;
+ return QCString(s1.str()+s2.str());
}
@@ -768,28 +455,28 @@ inline QCString operator+( const QCString &s1, const QGString &s2 );
inline QCString operator+( const QGString &s1, const QCString &s2 );
-Q_EXPORT inline QCString operator+( const QCString &s1, const char *s2 )
+inline QCString operator+( const QCString &s1, const char *s2 )
{
QCString tmp(s1);
tmp += s2;
return tmp;
}
-Q_EXPORT inline QCString operator+( const char *s1, const QCString &s2 )
+inline QCString operator+( const char *s1, const QCString &s2 )
{
QCString tmp(s1);
tmp += s2;
return tmp;
}
-Q_EXPORT inline QCString operator+( const QCString &s1, char c2 )
+inline QCString operator+( const QCString &s1, char c2 )
{
QCString tmp( s1.data() );
tmp += c2;
return tmp;
}
-Q_EXPORT inline QCString operator+( char c1, const QCString &s2 )
+inline QCString operator+( char c1, const QCString &s2 )
{
QCString tmp;
tmp += c1;
@@ -807,14 +494,25 @@ inline const char *qPrint(const QCString &s)
if (!s.isEmpty()) return s.data(); else return "";
}
+inline const char *qPrint(const std::string &s)
+{
+ return s.c_str();
+}
+
inline std::string toStdString(const QCString &s)
{
- if (!s.isEmpty()) return std::string(s.data()); else return std::string();
+ return s.str();
}
// helper functions
-QCString substitute(const QCString &s,const QCString &src,const QCString &dst);
+QCString substitute(const QCString &str,const QCString &find,const QCString &replace);
QCString substitute(const QCString &s,const QCString &src,const QCString &dst,int skip_seq);
-QCString substitute(const QCString &s,char srcChar,char dstChar);
+
+inline QCString substitute(const QCString &s,char srcChar,char dstChar)
+{
+ std::string ss = s.str();
+ ss.replace(ss.begin(),ss.end(),srcChar,dstChar);
+ return ss;
+}
#endif // QCSTRING_H