Blame qtools/qcstring.h

Packit 1c1d7e
/****************************************************************************
Packit 1c1d7e
**
Packit 1c1d7e
** Copyright (C) 1997-2015 by Dimitri van Heesch.
Packit 1c1d7e
**
Packit 1c1d7e
** Permission to use, copy, modify, and distribute this software and its
Packit 1c1d7e
** documentation under the terms of the GNU General Public License is hereby
Packit 1c1d7e
** granted. No representations are made about the suitability of this software
Packit 1c1d7e
** for any purpose. It is provided "as is" without express or implied warranty.
Packit 1c1d7e
** See the GNU General Public License for more details.
Packit 1c1d7e
**
Packit 1c1d7e
** Note: this is a reimplementation of the qcstring.h that came with
Packit 1c1d7e
** an Qt version 2.2.3. For short strings it stores the string data inside
Packit 1c1d7e
** the object. For long strings it uses a separate array with reference counting.
Packit 1c1d7e
**
Packit 1c1d7e
**********************************************************************/
Packit 1c1d7e
Packit 1c1d7e
#ifndef QCSTRING_H
Packit 1c1d7e
#define QCSTRING_H
Packit 1c1d7e
Packit 1c1d7e
#ifndef QT_H
Packit 1c1d7e
#include "qarray.h"
Packit 1c1d7e
#endif // QT_H
Packit 1c1d7e
Packit 1c1d7e
#include <stdio.h>
Packit 1c1d7e
#include <stdlib.h>
Packit 1c1d7e
#include <string.h>
Packit 1c1d7e
Packit 1c1d7e
#if !defined(_OS_WIN32_) || defined(__MINGW32__)
Packit 1c1d7e
#include <stdint.h>
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_SUN_) && defined(_CC_GNU_)
Packit 1c1d7e
#include <strings.h>
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
#include <assert.h>
Packit 1c1d7e
Packit 1c1d7e
class QGString;
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  Fixes and workarounds for some platforms
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_HPUX_)
Packit 1c1d7e
// HP-UX has badly defined strstr() etc.
Packit 1c1d7e
// ### fix in 3.0: change hack_* to qt_hack_*
Packit 1c1d7e
// by the way HP-UX is probably right, the standard has evolved and
Packit 1c1d7e
// we'll have to adapt to it
Packit 1c1d7e
inline char *hack_strstr( const char *s1, const char *s2 )
Packit 1c1d7e
{ return (char *)strstr(s1, s2); }
Packit 1c1d7e
inline char *hack_strchr( const char *s, int c )
Packit 1c1d7e
{ return (char *)strchr(s, c); }
Packit 1c1d7e
inline char *hack_strrchr( const char *s, int c )
Packit 1c1d7e
{ return (char *)strrchr(s, c); }
Packit 1c1d7e
#define strstr(s1,s2)	hack_strstr((s1),(s2))
Packit 1c1d7e
#define strchr(s,c)	hack_strchr((s),(c))
Packit 1c1d7e
#define strrchr(s,c)	hack_strrchr((s),(c))
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  Safe and portable C string functions; extensions to standard string.h
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT void *qmemmove( void *dst, const void *src, uint len );
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_SUN_) || defined(_CC_OC_)
Packit 1c1d7e
#define memmove(s1,s2,n) qmemmove((s1),(s2),(n))
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_WIN32_)
Packit 1c1d7e
#define qsnprintf _snprintf
Packit 1c1d7e
#else
Packit 1c1d7e
#define qsnprintf snprintf
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT char *qstrdup( const char * );
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline uint cstrlen( const char *str )
Packit 1c1d7e
{ return (uint)strlen(str); }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline uint qstrlen( const char *str )
Packit 1c1d7e
{ return str ? (uint)strlen(str) : 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline char *cstrcpy( char *dst, const char *src )
Packit 1c1d7e
{ return strcpy(dst,src); }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline char *qstrcpy( char *dst, const char *src )
Packit 1c1d7e
{ return src ? strcpy(dst, src) : 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT char * qstrncpy(char *src,const char *dst, uint len);
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline int cstrcmp( const char *str1, const char *str2 )
Packit 1c1d7e
{ return strcmp(str1,str2); }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline int qstrcmp( const char *str1, const char *str2 )
Packit 1c1d7e
{ return (str1 && str2) ? strcmp(str1,str2) : (int)((intptr_t)str2 - (intptr_t)str1); }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline int cstrncmp( const char *str1, const char *str2, uint len )
Packit 1c1d7e
{ return strncmp(str1,str2,len); }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline int qstrncmp( const char *str1, const char *str2, uint len )
Packit 1c1d7e
{ return (str1 && str2) ? strncmp(str1,str2,len) :
Packit 1c1d7e
			  (int)((intptr_t)str2 - (intptr_t)str1); }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT int qstricmp( const char *str1, const char *str2 );
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT int qstrnicmp( const char *str1, const char *str2, uint len );
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QByteArray class
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
#if defined(Q_TEMPLATEDLL)
Packit 1c1d7e
template class Q_EXPORT QArray<char>;
Packit 1c1d7e
#endif
Packit 1c1d7e
typedef QArray<char> QByteArray;
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QByteArray stream functions
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
#ifndef QT_NO_DATASTREAM
Packit 1c1d7e
Q_EXPORT QDataStream &operator<<( QDataStream &, const QByteArray & );
Packit 1c1d7e
Q_EXPORT QDataStream &operator>>( QDataStream &, QByteArray & );
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
class QRegExp;
Packit 1c1d7e
Packit 1c1d7e
/** This is an alternative implementation of QCString. It provides basically
Packit 1c1d7e
 *  the same functions but uses reference counting and copy on write.
Packit 1c1d7e
 */
Packit 1c1d7e
class QCString
Packit 1c1d7e
{
Packit 1c1d7e
public:
Packit 1c1d7e
    /** creates an empty string */
Packit 1c1d7e
    QCString() : m_rep()
Packit 1c1d7e
    {
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** destroys the string */
Packit 1c1d7e
   ~QCString()
Packit 1c1d7e
    {
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** makes a copy of a string. */
Packit 1c1d7e
    QCString( const QCString &s ) : m_rep(s.m_rep)
Packit 1c1d7e
    {
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** creates a string with room for size characters
Packit 1c1d7e
     *  @param[in] size the number of character to allocate (including the 0-terminator)
Packit 1c1d7e
     */
Packit 1c1d7e
    explicit QCString( int size ) : m_rep(size)
Packit 1c1d7e
    {
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** creates a string from a plain C string.
Packit 1c1d7e
     *  @param[in] str A zero terminated C string. When 0 an empty string is created.
Packit 1c1d7e
     */
Packit 1c1d7e
    QCString( const char *str ) : m_rep(str)
Packit 1c1d7e
    {
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** creates a string from \a str and copies over the first \a maxlen characters. */
Packit 1c1d7e
    QCString( const char *str, uint maxlen ) : m_rep(str,maxlen)
Packit 1c1d7e
    {
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** replaces the contents by that of string \a s. */
Packit 1c1d7e
    QCString &operator=( const QCString &s )
Packit 1c1d7e
    {
Packit 1c1d7e
      m_rep = s.m_rep;
Packit 1c1d7e
      return *this;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** replaces the contents by that of C string \a str. */
Packit 1c1d7e
    QCString &operator=( const char *str)
Packit 1c1d7e
    {
Packit 1c1d7e
      m_rep = str;
Packit 1c1d7e
      return *this;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns TRUE iff the string is empty. Equivalent to isEmpty(). */
Packit 1c1d7e
    bool isNull() const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.isEmpty();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns TRUE iff the string is empty */
Packit 1c1d7e
    bool isEmpty() const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.isEmpty();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns the length of the string, excluding the 0-terminator. Equivalent to size(). */
Packit 1c1d7e
    uint length() const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.length();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns the length of the string, excluding the 0-terminator. */
Packit 1c1d7e
    uint size() const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.length();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns a pointer to the contents of the string in the form of a 0-terminated C string */
Packit 1c1d7e
    const char *data() const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.data();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns a writable pointer to the data.
Packit 1c1d7e
     *  @warning if the string is shared it will modifying the string directly and
Packit 1c1d7e
     *  this will overwrite all copies as well!
Packit 1c1d7e
     */
Packit 1c1d7e
    char *rawData() const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.rawData();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Resizes the string to hold \a newlen characters
Packit 1c1d7e
     *  (this value should include the 0-terminator). If the string is enlarged the contents will
Packit 1c1d7e
     *  be left unmodified.
Packit 1c1d7e
     */
Packit 1c1d7e
    bool resize( uint newlen )
Packit 1c1d7e
    {
Packit 1c1d7e
      m_rep.resize(newlen);
Packit 1c1d7e
      return TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Truncates the string at position \a pos. */
Packit 1c1d7e
    bool truncate( uint pos )
Packit 1c1d7e
    {
Packit 1c1d7e
      return resize(pos+1);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Fills a string with a predefined character
Packit 1c1d7e
     *  @param[in] c the character used to fill the string with.
Packit 1c1d7e
     *  @param[in] len the number of character to fill. Use -1 to fill the whole string.
Packit 1c1d7e
     *  @note the string will be resized to contain \a len characters. The contents of the
Packit 1c1d7e
     *  string will be lost.
Packit 1c1d7e
     */
Packit 1c1d7e
    bool fill( char c, int len = -1 )
Packit 1c1d7e
    {
Packit 1c1d7e
      m_rep.fill(c,len);
Packit 1c1d7e
      return TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns a deep copy of the string. */
Packit 1c1d7e
    QCString copy() const
Packit 1c1d7e
    {
Packit 1c1d7e
      if (length()==0) return QCString();
Packit 1c1d7e
      QCString cs(length()+1);
Packit 1c1d7e
      memcpy(cs.rawData(),data(),length());
Packit 1c1d7e
      return cs;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    QCString &sprintf( const char *format, ... );
Packit 1c1d7e
    int	find( char c, int index=0, bool cs=TRUE ) const;
Packit 1c1d7e
    int	find( const char *str, int index=0, bool cs=TRUE ) const;
Packit 1c1d7e
    int find( const QCString &str, int index=0, bool cs=TRUE ) const;
Packit 1c1d7e
    int	find( const QRegExp &rx, int index=0 ) const;
Packit 1c1d7e
    int	findRev( char c, int index=-1, bool cs=TRUE) const;
Packit 1c1d7e
    int	findRev( const char *str, int index=-1, bool cs=TRUE) const;
Packit 1c1d7e
    int	findRev( const QRegExp &rx, int index=-1 ) const;
Packit 1c1d7e
    int	contains( char c, bool cs=TRUE ) const;
Packit 1c1d7e
    int	contains( const char *str, bool cs=TRUE ) const;
Packit 1c1d7e
    int contains( const QRegExp &rx ) const;
Packit 1c1d7e
    bool stripPrefix(const char *prefix);
Packit 1c1d7e
    QCString left( uint len ) const;
Packit 1c1d7e
    QCString right( uint len ) const;
Packit 1c1d7e
    QCString mid( uint index, uint len=0xffffffff) const;
Packit 1c1d7e
    QCString lower() const;
Packit 1c1d7e
    QCString upper() const;
Packit 1c1d7e
    QCString stripWhiteSpace() const;
Packit 1c1d7e
    QCString simplifyWhiteSpace() const;
Packit 1c1d7e
    QCString &assign( const char *str );
Packit 1c1d7e
    QCString &insert( uint index, const char *s );
Packit 1c1d7e
    QCString &insert( uint index, char c);
Packit 1c1d7e
    QCString &append( const char *s );
Packit 1c1d7e
    QCString &prepend( const char *s );
Packit 1c1d7e
    QCString &remove( uint index, uint len );
Packit 1c1d7e
    QCString &replace( uint index, uint len, const char *s);
Packit 1c1d7e
    QCString &replace( const QRegExp &rx, const char *str );
Packit 1c1d7e
    short toShort( bool *ok=0 ) const;
Packit 1c1d7e
    ushort toUShort( bool *ok=0 ) const;
Packit 1c1d7e
    int	toInt( bool *ok=0 ) const;
Packit 1c1d7e
    uint toUInt( bool *ok=0 ) const;
Packit 1c1d7e
    long toLong( bool *ok=0 ) const;
Packit 1c1d7e
    ulong toULong( bool *ok=0 )	const;
Packit 1c1d7e
    uint64 toUInt64( bool *ok=0 ) const;
Packit 1c1d7e
    QCString &setNum(short n);
Packit 1c1d7e
    QCString &setNum(ushort n);
Packit 1c1d7e
    QCString &setNum(int n);
Packit 1c1d7e
    QCString &setNum(uint n);
Packit 1c1d7e
    QCString &setNum(long n);
Packit 1c1d7e
    QCString &setNum(ulong n);
Packit 1c1d7e
Packit 1c1d7e
    /** Converts the string to a plain C string */
Packit 1c1d7e
    operator const char *() const
Packit 1c1d7e
    {
Packit 1c1d7e
      return (const char *)data();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Appends string \a str to this string and returns a reference to the result. */
Packit 1c1d7e
    QCString &operator+=( const char *str )
Packit 1c1d7e
    {
Packit 1c1d7e
      if (!str) return *this;
Packit 1c1d7e
      int len1 = length();
Packit 1c1d7e
      int len2 = (int)strlen(str);
Packit 1c1d7e
      resize(len1+len2+1);
Packit 1c1d7e
      memcpy(rawData()+len1,str,len2);
Packit 1c1d7e
      return *this;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Appends character \a c to this string and returns a reference to the result. */
Packit 1c1d7e
    QCString &operator+=( char c )
Packit 1c1d7e
    {
Packit 1c1d7e
      int len = length();
Packit 1c1d7e
      resize(len+2);
Packit 1c1d7e
      rawData()[len]=c;
Packit 1c1d7e
      return *this;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Returns a reference to the character at index \a i. */
Packit 1c1d7e
    char &at( uint i) const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.at(i);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    /** Indexing operator. Equavalent to at(). */
Packit 1c1d7e
    char &operator[]( int i ) const
Packit 1c1d7e
    {
Packit 1c1d7e
      return m_rep.at((uint)i);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
  private:
Packit 1c1d7e
Packit 1c1d7e
    struct LSData;
Packit 1c1d7e
Packit 1c1d7e
    // long string representation
Packit 1c1d7e
    struct LongStringRep
Packit 1c1d7e
    {
Packit 1c1d7e
      uchar isShort; // : 1;  // should be shared with ShortStringRep
Packit 1c1d7e
      //uchar : 7;
Packit 1c1d7e
      LSData *d;
Packit 1c1d7e
    };
Packit 1c1d7e
Packit 1c1d7e
#define SHORT_STR_CAPACITY ((int)sizeof(LongStringRep)-2)
Packit 1c1d7e
#define SHORT_STR_MAX_LEN (SHORT_STR_CAPACITY-1)
Packit 1c1d7e
Packit 1c1d7e
    // short string representation
Packit 1c1d7e
    struct ShortStringRep
Packit 1c1d7e
    {
Packit 1c1d7e
      uchar isShort; // : 1;  // should be shared with LongStringRep
Packit 1c1d7e
      uchar len; //     : 7;
Packit 1c1d7e
      char str[SHORT_STR_CAPACITY]; // size including 0-terminator
Packit 1c1d7e
    };
Packit 1c1d7e
Packit 1c1d7e
    // ref counting string header
Packit 1c1d7e
    struct LSHeader
Packit 1c1d7e
    {
Packit 1c1d7e
      int           len;      // length of string without 0 terminator
Packit 1c1d7e
      int           refCount; // -1=leaked, 0=one ref & non-cost, n>0, n+1 refs, const
Packit 1c1d7e
    };
Packit 1c1d7e
    // ref counting string data and methods
Packit 1c1d7e
    struct LSData : public LSHeader
Packit 1c1d7e
    {
Packit 1c1d7e
      char *toStr()
Packit 1c1d7e
      {
Packit 1c1d7e
        return (char*)(this+1); // string data starts after the header
Packit 1c1d7e
      }
Packit 1c1d7e
Packit 1c1d7e
      // creates a LSData item with room for size bytes (which includes the 0 terminator!)
Packit 1c1d7e
      // if size is zero, an empty string will be created.
Packit 1c1d7e
      static LSData *create(int size)
Packit 1c1d7e
      {
Packit 1c1d7e
        LSData *data;
Packit 1c1d7e
        data = (LSData*)malloc(sizeof(LSHeader)+size);
Packit 1c1d7e
        data->len = size-1;
Packit 1c1d7e
        data->refCount = 0;
Packit 1c1d7e
        data->toStr()[size-1] = 0;
Packit 1c1d7e
        return data;
Packit 1c1d7e
      }
Packit 1c1d7e
      // remove out reference to the data. Frees memory if no more users
Packit 1c1d7e
      void dispose()
Packit 1c1d7e
      {
Packit 1c1d7e
        if (--refCount<0) free(this);
Packit 1c1d7e
      }
Packit 1c1d7e
Packit 1c1d7e
      // resizes LSData so it can hold size bytes (which includes the 0 terminator!)
Packit 1c1d7e
      // Since this is for long strings only, size should be > SHORT_STR_CAPACITY
Packit 1c1d7e
      static LSData *resize(LSData *d,int size)
Packit 1c1d7e
      {
Packit 1c1d7e
        if (d->len>0 && d->refCount==0) // non-const, non-empty
Packit 1c1d7e
        {
Packit 1c1d7e
          d = (LSData*)realloc(d,sizeof(LSHeader)+size);
Packit 1c1d7e
          d->len = size-1;
Packit 1c1d7e
          d->toStr()[size-1] = 0;
Packit 1c1d7e
          return d;
Packit 1c1d7e
        }
Packit 1c1d7e
        else // need to make a copy
Packit 1c1d7e
        {
Packit 1c1d7e
          LSData *newData = LSData::create(size);
Packit 1c1d7e
          int len = d->len;
Packit 1c1d7e
          if (len>=size) len=size-1;
Packit 1c1d7e
          memcpy(newData->toStr(),d->toStr(),len);
Packit 1c1d7e
          newData->toStr()[len]=0;
Packit 1c1d7e
          d->dispose();
Packit 1c1d7e
          return newData;
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    };
Packit 1c1d7e
Packit 1c1d7e
    class StringRep
Packit 1c1d7e
    {
Packit 1c1d7e
      public:
Packit 1c1d7e
        StringRep()
Packit 1c1d7e
        {
Packit 1c1d7e
          initEmpty();
Packit 1c1d7e
        }
Packit 1c1d7e
        void initEmpty()
Packit 1c1d7e
        {
Packit 1c1d7e
          u.s.isShort=TRUE;
Packit 1c1d7e
          u.s.len=0;
Packit 1c1d7e
          //memset(u.s.str,0,SHORT_STR_CAPACITY);
Packit 1c1d7e
        }
Packit 1c1d7e
       ~StringRep()
Packit 1c1d7e
        {
Packit 1c1d7e
          if (!u.s.isShort)
Packit 1c1d7e
          {
Packit 1c1d7e
            u.l.d->dispose();
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        StringRep(const StringRep &s)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (&s!=this)
Packit 1c1d7e
          {
Packit 1c1d7e
            u.s.isShort = s.u.s.isShort;
Packit 1c1d7e
            if (s.u.s.isShort)
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = s.u.s.len;
Packit 1c1d7e
              memcpy(u.s.str,s.u.s.str,s.u.s.len+1);
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d = s.u.l.d;
Packit 1c1d7e
              u.l.d->refCount++;
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // self-assignment
Packit 1c1d7e
          {
Packit 1c1d7e
            u = s.u; // avoid uninitialized warning from gcc
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        StringRep(int size)
Packit 1c1d7e
        {
Packit 1c1d7e
          u.s.isShort = size<=SHORT_STR_CAPACITY;
Packit 1c1d7e
          if (size<=SHORT_STR_CAPACITY) // init short string
Packit 1c1d7e
          {
Packit 1c1d7e
            if (size>0)
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = size-1;
Packit 1c1d7e
              u.s.str[size-1]='\0';
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = 0;
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // int long string
Packit 1c1d7e
          {
Packit 1c1d7e
            u.l.d = LSData::create(size);
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        StringRep(const char *str)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (str)
Packit 1c1d7e
          {
Packit 1c1d7e
            int len = (int)strlen(str);
Packit 1c1d7e
            u.s.isShort = len
Packit 1c1d7e
            if (len
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = len;
Packit 1c1d7e
              qstrncpy(u.s.str,str,SHORT_STR_CAPACITY);
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d = LSData::create(len+1);
Packit 1c1d7e
              memcpy(u.l.d->toStr(),str,u.l.d->len);
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // create empty string
Packit 1c1d7e
          {
Packit 1c1d7e
            initEmpty();
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        StringRep( const char *str, uint maxlen )
Packit 1c1d7e
        {
Packit 1c1d7e
          if (str && maxlen>0)
Packit 1c1d7e
          {
Packit 1c1d7e
            uint len=(uint)strlen(str);
Packit 1c1d7e
            if (len>maxlen) len=maxlen;
Packit 1c1d7e
            u.s.isShort = len<=SHORT_STR_MAX_LEN;
Packit 1c1d7e
            if (u.s.isShort)
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = len;
Packit 1c1d7e
              memcpy(u.s.str,str,len);
Packit 1c1d7e
              u.s.str[len]='\0';
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d = LSData::create(len+1);
Packit 1c1d7e
              memcpy(u.l.d->toStr(),str,len);
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // create empty string
Packit 1c1d7e
          {
Packit 1c1d7e
            initEmpty();
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        StringRep &operator=(const StringRep &s)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (&s!=this)
Packit 1c1d7e
          {
Packit 1c1d7e
            if (!u.s.isShort)
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d->dispose();
Packit 1c1d7e
            }
Packit 1c1d7e
            u.s.isShort = s.u.s.isShort;
Packit 1c1d7e
            if (u.s.isShort) // copy by value
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = s.u.s.len;
Packit 1c1d7e
              memcpy(u.s.str,s.u.s.str,s.u.s.len+1);
Packit 1c1d7e
            }
Packit 1c1d7e
            else // copy by reference
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d = s.u.l.d;
Packit 1c1d7e
              u.l.d->refCount++;
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // self-assignment
Packit 1c1d7e
          {
Packit 1c1d7e
            u = s.u; // avoid uninitialized warning from gcc
Packit 1c1d7e
          }
Packit 1c1d7e
          return *this;
Packit 1c1d7e
        }
Packit 1c1d7e
        StringRep &operator=(const char *str)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (!u.s.isShort)
Packit 1c1d7e
          {
Packit 1c1d7e
            u.l.d->dispose();
Packit 1c1d7e
          }
Packit 1c1d7e
          if (str)
Packit 1c1d7e
          {
Packit 1c1d7e
            int len = (int)strlen(str);
Packit 1c1d7e
            u.s.isShort = len
Packit 1c1d7e
            if (len
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = len;
Packit 1c1d7e
              qstrncpy(u.s.str,str,SHORT_STR_CAPACITY);
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d = LSData::create(len+1);
Packit 1c1d7e
              memcpy(u.l.d->toStr(),str,len);
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            initEmpty();
Packit 1c1d7e
          }
Packit 1c1d7e
          return *this;
Packit 1c1d7e
        }
Packit 1c1d7e
        bool isEmpty() const
Packit 1c1d7e
        {
Packit 1c1d7e
          return u.s.isShort && u.s.len==0;
Packit 1c1d7e
        }
Packit 1c1d7e
        uint length() const
Packit 1c1d7e
        {
Packit 1c1d7e
          uint l = u.s.isShort ? u.s.len : u.l.d->len;
Packit 1c1d7e
          return l;
Packit 1c1d7e
        }
Packit 1c1d7e
        const char *data() const
Packit 1c1d7e
        {
Packit 1c1d7e
          if (u.s.isShort)
Packit 1c1d7e
          {
Packit 1c1d7e
            return u.s.len==0 ? 0 : u.s.str;
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            return u.l.d->len==0 ? 0 : u.l.d->toStr();
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        char *rawData() const
Packit 1c1d7e
        {
Packit 1c1d7e
          if (u.s.isShort)
Packit 1c1d7e
          {
Packit 1c1d7e
            return u.s.len==0 ? 0 : (char*)u.s.str;
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            //assert(u.l.d->refCount==0); // string may not be shared when accessed raw
Packit 1c1d7e
            return u.l.d->len==0 ? 0 : u.l.d->toStr();
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        char &at(int i) const
Packit 1c1d7e
        {
Packit 1c1d7e
          if (u.s.isShort)
Packit 1c1d7e
          {
Packit 1c1d7e
            return (char&)u.s.str[i];
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            return u.l.d->toStr()[i];
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        bool resize( uint newlen )
Packit 1c1d7e
        {
Packit 1c1d7e
          if (u.s.isShort && newlen<=SHORT_STR_CAPACITY) // resize short string
Packit 1c1d7e
          {
Packit 1c1d7e
            if (newlen>0)
Packit 1c1d7e
            {
Packit 1c1d7e
              u.s.len = newlen-1;
Packit 1c1d7e
              u.s.str[newlen-1]='\0';
Packit 1c1d7e
            }
Packit 1c1d7e
            else // string becomes empty
Packit 1c1d7e
            {
Packit 1c1d7e
              initEmpty();
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else if (u.s.isShort) // turn short string into long string
Packit 1c1d7e
          {
Packit 1c1d7e
            StringRep tmp = *this;
Packit 1c1d7e
            u.s.isShort=FALSE;
Packit 1c1d7e
            u.l.d = LSData::create(newlen);
Packit 1c1d7e
            if (tmp.u.s.len>0)
Packit 1c1d7e
            {
Packit 1c1d7e
              memcpy(u.l.d->toStr(),tmp.u.s.str,tmp.u.s.len+1);
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d->toStr()[0]='\0';
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else if (!u.s.isShort && newlen<=SHORT_STR_CAPACITY) // turn long string into short string
Packit 1c1d7e
          {
Packit 1c1d7e
            if (newlen>0)
Packit 1c1d7e
            {
Packit 1c1d7e
              StringRep tmp(newlen); // copy short part into tmp buffer
Packit 1c1d7e
              memcpy(tmp.u.s.str,u.l.d->toStr(),newlen-1);
Packit 1c1d7e
              tmp.u.s.str[newlen-1]='\0';
Packit 1c1d7e
              u.l.d->dispose();
Packit 1c1d7e
              u.s = tmp.u.s;
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              u.l.d->dispose();
Packit 1c1d7e
              initEmpty();
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          else // resize long string
Packit 1c1d7e
          {
Packit 1c1d7e
            u.l.d = u.l.d->resize(u.l.d,newlen);
Packit 1c1d7e
          }
Packit 1c1d7e
          return TRUE;
Packit 1c1d7e
        }
Packit 1c1d7e
        bool fill( char c, int len )
Packit 1c1d7e
        {
Packit 1c1d7e
          if (len<0) len=length();
Packit 1c1d7e
          if (!u.s.isShort) // detach from shared string
Packit 1c1d7e
          {
Packit 1c1d7e
            resize(len+1);
Packit 1c1d7e
          }
Packit 1c1d7e
          else if (len!=(int)length())
Packit 1c1d7e
          {
Packit 1c1d7e
            if (len>0)
Packit 1c1d7e
            {
Packit 1c1d7e
              resize(len+1);
Packit 1c1d7e
            }
Packit 1c1d7e
          }
Packit 1c1d7e
          if (len>0)
Packit 1c1d7e
          {
Packit 1c1d7e
            memset(rawData(),c,len);
Packit 1c1d7e
          }
Packit 1c1d7e
          return TRUE;
Packit 1c1d7e
        }
Packit 1c1d7e
      private:
Packit 1c1d7e
        union ShortOrLongStringSelector
Packit 1c1d7e
        {
Packit 1c1d7e
          ShortStringRep s;
Packit 1c1d7e
          LongStringRep  l;
Packit 1c1d7e
        } u;
Packit 1c1d7e
    };
Packit 1c1d7e
    StringRep m_rep;
Packit 1c1d7e
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QCString stream functions
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
#ifndef QT_NO_DATASTREAM
Packit 1c1d7e
Q_EXPORT QDataStream &operator<<( QDataStream &, const QCString & );
Packit 1c1d7e
Q_EXPORT QDataStream &operator>>( QDataStream &, QCString & );
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QCString non-member operators
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator==( const QCString &s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2.data()) == 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator==( const QCString &s1, const char *s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2) == 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator==( const char *s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1,s2.data()) == 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator!=( const QCString &s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2.data()) != 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator!=( const QCString &s1, const char *s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2) != 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator!=( const char *s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1,s2.data()) != 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator<( const QCString &s1, const QCString& s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2.data()) < 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator<( const QCString &s1, const char *s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2) < 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator<( const char *s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1,s2.data()) < 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator<=( const QCString &s1, const char *s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2) <= 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator<=( const char *s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1,s2.data()) <= 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator>( const QCString &s1, const char *s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2) > 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator>( const char *s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1,s2.data()) > 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator>=( const QCString &s1, const char *s2 )
Packit 1c1d7e
{ return qstrcmp(s1.data(),s2) >= 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline bool operator>=( const char *s1, const QCString &s2 )
Packit 1c1d7e
{ return qstrcmp(s1,s2.data()) >= 0; }
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline QCString operator+( const QCString &s1, const QCString &s2 )
Packit 1c1d7e
{
Packit 1c1d7e
    QCString tmp(s1);
Packit 1c1d7e
    tmp += s2;
Packit 1c1d7e
    return tmp;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
inline QCString operator+( const QCString &s1, const QGString &s2 );
Packit 1c1d7e
inline QCString operator+( const QGString &s1, const QCString &s2 );
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline QCString operator+( const QCString &s1, const char *s2 )
Packit 1c1d7e
{
Packit 1c1d7e
    QCString tmp(s1);
Packit 1c1d7e
    tmp += s2;
Packit 1c1d7e
    return tmp;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline QCString operator+( const char *s1, const QCString &s2 )
Packit 1c1d7e
{
Packit 1c1d7e
    QCString tmp(s1);
Packit 1c1d7e
    tmp += s2;
Packit 1c1d7e
    return tmp;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline QCString operator+( const QCString &s1, char c2 )
Packit 1c1d7e
{
Packit 1c1d7e
    QCString tmp( s1.data() );
Packit 1c1d7e
    tmp += c2;
Packit 1c1d7e
    return tmp;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Q_EXPORT inline QCString operator+( char c1, const QCString &s2 )
Packit 1c1d7e
{
Packit 1c1d7e
    QCString tmp;
Packit 1c1d7e
    tmp += c1;
Packit 1c1d7e
    tmp += s2;
Packit 1c1d7e
    return tmp;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
inline const char *qPrint(const char *s)
Packit 1c1d7e
{
Packit 1c1d7e
  if (s) return s; else return "";
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
inline const char *qPrint(const QCString &s)
Packit 1c1d7e
{
Packit 1c1d7e
  if (!s.isEmpty()) return s.data(); else return "";
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
#endif // QCSTRING_H