src/qt3support/tools/q3cstring.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/qt3support/tools/q3cstring.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1072 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3cstring.h"
+#include "qregexp.h"
+#include "qdatastream.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+/*****************************************************************************
+  Q3CString member functions
+ *****************************************************************************/
+
+/*!
+    \class Q3CString
+    \reentrant
+    \brief The Q3CString class provides an abstraction of the classic C
+    zero-terminated char array (char *).
+
+    \compat
+
+    Q3CString tries to behave like a more convenient \c{const char *}.
+    The price of doing this is that some algorithms will perform
+    badly. For example, append() is O(length()) since it scans for a
+    null terminator. Although you might use Q3CString for text that is
+    never exposed to the user, for most purposes, and especially for
+    user-visible text, you should use QString. QString provides
+    implicit sharing, Unicode and other internationalization support,
+    and is well optimized.
+
+    Note that for the Q3CString methods that take a \c{const char *}
+    parameter the \c{const char *} must either be 0 (null) or not-null
+    and '\0' (NUL byte) terminated; otherwise the results are
+    undefined.
+
+    A default constructed Q3CString is \e null, i.e. both the length
+    and the data pointer are 0 and isNull() returns true.
+    
+    \note However, if you ask for the data pointer of a null Q3CString
+    by calling data(), then because the internal representation of the
+    null Q3CString is shared, it will be detached and replaced with a
+    non-shared, empty representation, a non-null data pointer will be
+    returned, and subsequent calls to isNull() will return false. But
+    if you ask for the data pointer of a null Q3CString by calling
+    constData(), the shared internal representation is not detached, a
+    null data pointer is returned, and subsequent calls to isNull()
+    will continue to return true.
+
+    A Q3CString that references the empty string ("", a single '\0'
+    char) is \e empty, i.e. isEmpty() returns true.  Both null and
+    empty Q3CStrings are legal parameters to the methods.  Assigning
+    \c{const char *} 0 to Q3CString produces a null Q3CString.
+
+    The length() function returns the length of the string; resize()
+    resizes the string and truncate() truncates the string. A string
+    can be filled with a character using fill(). Strings can be left
+    or right padded with characters using leftJustify() and
+    rightJustify(). Characters, strings and regular expressions can be
+    searched for using find() and findRev(), and counted using
+    contains().
+
+    Strings and characters can be inserted with insert() and appended
+    with append(). A string can be prepended with prepend().
+    Characters can be removed from the string with remove() and
+    replaced with replace().
+
+    Portions of a string can be extracted using left(), right() and
+    mid(). Whitespace can be removed using stripWhiteSpace() and
+    simplifyWhiteSpace(). Strings can be converted to uppercase or
+    lowercase with upper() and lower() respectively.
+
+    Strings that contain numbers can be converted to numbers with
+    toShort(), toInt(), toLong(), toULong(), toFloat() and toDouble().
+    Numbers can be converted to strings with setNum().
+
+    Many operators are overloaded to work with Q3CStrings. Q3CString
+    also supports some more obscure functions, e.g. sprintf(),
+    setStr() and setExpand().
+
+    \sidebar Note on Character Comparisons
+
+    In Q3CString the notion of uppercase and lowercase and of which
+    character is greater than or less than another character is locale
+    dependent. This affects functions which support a case insensitive
+    option or which compare or lowercase or uppercase their arguments.
+    Case insensitive operations and comparisons will be accurate if
+    both strings contain only ASCII characters. (If \c $LC_CTYPE is
+    set, most Unix systems do "the right thing".) Functions that this
+    affects include contains(), find(), findRev(), \l operator<(), \l
+    operator<=(), \l operator>(), \l operator>=(), lower() and
+    upper().
+
+    This issue does not apply to \l{QString}s since they represent
+    characters using Unicode.
+    \endsidebar
+
+    Performance note: The Q3CString methods for QRegExp searching are
+    implemented by converting the Q3CString to a QString and performing
+    the search on that. This implies a deep copy of the Q3CString data.
+    If you are going to perform many QRegExp searches on a large
+    Q3CString, you will get better performance by converting the
+    Q3CString to a QString yourself, and then searching in the QString.
+*/
+
+/*!
+    \fn Q3CString Q3CString::left(uint len)  const
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString Q3CString::right(uint len) const
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString Q3CString::mid(uint index, uint len) const
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString  Q3CString::lower() const
+
+    Use QByteArray::toLower() instead.
+*/
+
+/*!
+    \fn Q3CString  Q3CString::upper() const
+
+    Use QByteArray::toUpper() instead.
+*/
+
+/*!
+    \fn Q3CString  Q3CString::stripWhiteSpace() const
+
+    Use QByteArray::trimmed() instead.
+*/
+
+/*!
+    \fn Q3CString  Q3CString::simplifyWhiteSpace() const
+
+    Use QByteArray::simplified() instead.
+*/
+
+/*!
+    \fn Q3CString& Q3CString::insert(uint index, const char *c)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::insert(uint index, char c)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::prepend(const char *c)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::remove(uint index, uint len)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::replace(uint index, uint len, const char *c)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::replace(char c, const Q3CString &after)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::replace(char c, const char *after)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::replace(const Q3CString &b, const Q3CString &a)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::replace(const char *b, const char *a)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString& Q3CString::replace(char b, char a)
+
+    \internal
+*/
+
+/*!
+    \fn Q3CString::Q3CString()
+
+    Constructs a null string.
+
+    \sa isNull()
+*/
+
+/*!
+    \fn Q3CString::Q3CString(const QByteArray &ba)
+
+    Constructs a copy of \a ba.
+*/
+
+/*!
+    \fn Q3CString::Q3CString(const Q3CString &s)
+
+    Constructs a shallow copy \a s.
+*/
+
+/*! \fn Q3CString::Q3CString(int size)
+    Constructs a string with room for \a size characters, including
+    the '\0'-terminator. Makes a null string if \a size == 0.
+
+    If \a size \> 0, then the first and last characters in the string
+    are initialized to '\0'. All other characters are uninitialized.
+
+    \sa resize(), isNull()
+*/
+
+/*! \fn Q3CString::Q3CString(const char *str)
+    Constructs a string that is a deep copy of \a str.
+
+    If \a str is 0 a null string is created.
+
+    \sa isNull()
+*/
+
+
+/*! \fn Q3CString::Q3CString(const char *str, uint maxsize)
+
+    Constructs a string that is a deep copy of \a str. The copy will
+    be at most \a maxsize bytes long including the '\0'-terminator.
+
+    Example:
+    \snippet doc/src/snippets/code/src_qt3support_tools_q3cstring.cpp 0
+
+    If \a str contains a 0 byte within the first \a maxsize bytes, the
+    resulting Q3CString will be terminated by this 0. If \a str is 0 a
+    null string is created.
+
+    \sa isNull()
+*/
+
+/*!
+    \fn Q3CString &Q3CString::operator=(const QByteArray &ba)
+
+    Assigns byte array \a ba to this Q3CString.
+*/
+
+/*!
+    \fn Q3CString &Q3CString::operator=(const Q3CString &s)
+
+    Assigns a shallow copy of \a s to this string and returns a
+    reference to this string.
+*/
+
+/*!
+    \fn Q3CString &Q3CString::operator=(const char *str)
+    \overload
+
+    Assigns a deep copy of \a str to this string and returns a
+    reference to this string.
+
+    If \a str is 0 a null string is created.
+
+    \sa isNull()
+*/
+
+/*
+    \fn bool Q3CString::isNull() const
+
+    Returns true if the string is null, i.e. if data() == 0; otherwise
+    returns false. A null string is also an empty string.
+
+    \note If you ask for the data pointer of a null Q3CString by
+    calling data(), then because the internal representation of the
+    null Q3CString is shared, it will be detached and replaced with a
+    non-shared, empty representation, a non-null data pointer will be
+    returned, and subsequent calls to isNull() will return false. But
+    if you ask for the data pointer of a null Q3CString by calling
+    constData(), the shared internal representation is not detached, a
+    null data pointer is returned, and subsequent calls to isNull()
+    will continue to return true.
+
+    Example:
+    \snippet doc/src/snippets/code/src.qt3support.tools.q3cstring.cpp 1
+
+    \sa isEmpty(), length(), size()
+*/
+
+/*
+    \fn bool Q3CString::isEmpty() const
+
+    Returns true if the string is empty, i.e. if length() == 0;
+    otherwise returns false. An empty string is not always a null
+    string.
+
+    See example in isNull().
+
+    \sa isNull(), length(), size()
+*/
+
+/*
+    \fn uint Q3CString::length() const
+
+    Returns the length of the string, excluding the '\0'-terminator.
+    Equivalent to calling \c strlen(data()).
+
+    Null strings and empty strings have zero length.
+
+    \sa size(), isNull(), isEmpty()
+*/
+
+/*
+    \fn bool Q3CString::truncate(uint pos)
+
+    Truncates the string at position \a pos.
+
+    Equivalent to calling \c resize(pos+1).
+
+    Example:
+    \snippet doc/src/snippets/code/src.qt3support.tools.q3cstring.cpp 2
+
+    \sa resize()
+*/
+
+
+
+/*!
+    Implemented as a call to the native vsprintf() (see the manual for
+    your C library).
+
+    If the string is shorter than 256 characters, this sprintf() calls
+    resize(256) to decrease the chance of memory corruption. The
+    string is resized back to its actual length before sprintf()
+    returns.
+
+    Example:
+    \snippet doc/src/snippets/code/src_qt3support_tools_q3cstring.cpp 3
+
+    \warning All vsprintf() implementations will write past the end of
+    the target string (*this) if the \a format specification and
+    arguments happen to be longer than the target string, and some
+    will also fail if the target string is longer than some arbitrary
+    implementation limit.
+
+    Giving user-supplied arguments to sprintf() is risky: Sooner or
+    later someone will paste a huge line into your application.
+*/
+
+Q3CString &Q3CString::sprintf(const char *format, ...)
+{
+    detach();
+    va_list ap;
+    va_start(ap, format);
+    if (size() < 256)
+        resize(256);                // make string big enough
+    qvsnprintf(data(), size(), format, ap);
+    resize(qstrlen(constData()));
+    va_end(ap);
+    return *this;
+}
+
+
+
+/*!
+    \fn Q3CString Q3CString::copy() const
+
+    Returns a deep copy of this string.
+*/
+
+
+/*!
+    Returns a string of length \a width (plus one for the terminating
+    '\0') that contains this string padded with the \a fill character.
+
+    If the length of the string exceeds \a width and \a truncate is
+    false (the default), then the returned string is a copy of the
+    string. If the length of the string exceeds \a width and \a
+    truncate is true, then the returned string is a left(\a width).
+
+    Example:
+    \snippet doc/src/snippets/code/src_qt3support_tools_q3cstring.cpp 4
+
+    \sa rightJustify()
+*/
+
+Q3CString Q3CString::leftJustify(uint width, char fill, bool truncate) const
+{
+    Q3CString result;
+    int len = qstrlen(constData());
+    int padlen = width - len;
+    if (padlen > 0) {
+        result.resize(len+padlen);
+        memcpy(result.data(), constData(), len);
+        memset(result.data()+len, fill, padlen);
+    } else {
+        if (truncate)
+            result = left(width);
+        else
+            result = *this;
+    }
+    return result;
+}
+
+/*!
+    Returns a string of length \a width (plus one for the terminating
+    '\0') that contains zero or more of the \a fill character followed
+    by this string.
+
+    If the length of the string exceeds \a width and \a truncate is
+    false (the default), then the returned string is a copy of the
+    string. If the length of the string exceeds \a width and \a
+    truncate is true, then the returned string is a left(\a width).
+
+    Example:
+    \snippet doc/src/snippets/code/src_qt3support_tools_q3cstring.cpp 5
+
+    \sa leftJustify()
+*/
+
+Q3CString Q3CString::rightJustify(uint width, char fill, bool truncate) const
+{
+    Q3CString result;
+    int len = qstrlen(constData());
+    int padlen = width - len;
+    if (padlen > 0) {
+        result.resize(len+padlen);
+        memset(result.data(), fill, padlen);
+        memcpy(result.data()+padlen, constData(), len);
+    } else {
+        if (truncate)
+            result = left(width);
+        else
+            result = *this;
+    }
+    return result;
+}
+
+/*!
+    Returns the string converted to a \c long value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, or if it has trailing garbage; otherwise *\a ok is set to
+    true.
+*/
+
+long Q3CString::toLong(bool *ok) const
+{
+    const char *p = constData();
+    long val=0;
+    const long max_mult = 214748364;
+    bool is_ok = false;
+    int neg = 0;
+    if (!p)
+        goto bye;
+    while (isspace((uchar) *p))                // skip leading space
+        p++;
+    if (*p == '-') {
+        p++;
+        neg = 1;
+    } else if (*p == '+') {
+        p++;
+    }
+    if (!isdigit((uchar) *p))
+        goto bye;
+    while (isdigit((uchar) *p)) {
+        if (val > max_mult || (val == max_mult && (*p-'0') > 7+neg))
+            goto bye;
+        val = 10*val + (*p++ - '0');
+    }
+    if (neg)
+        val = -val;
+    while (isspace((uchar) *p))                // skip trailing space
+        p++;
+    if (*p == '\0')
+        is_ok = true;
+bye:
+    if (ok)
+        *ok = is_ok;
+    return is_ok ? val : 0;
+}
+
+/*!
+    Returns the string converted to an \c{unsigned long} value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, or if it has trailing garbage; otherwise *\a ok is set to
+    true.
+*/
+
+ulong Q3CString::toULong(bool *ok) const
+{
+    const char *p = constData();
+    ulong val=0;
+    const ulong max_mult = 429496729;
+    bool is_ok = false;
+    if (!p)
+        goto bye;
+    while (isspace((uchar) *p))                // skip leading space
+        p++;
+    if (*p == '+')
+        p++;
+    if (!isdigit((uchar) *p))
+        goto bye;
+    while (isdigit((uchar) *p)) {
+        if (val > max_mult || (val == max_mult && (*p-'0') > 5))
+            goto bye;
+        val = 10*val + (*p++ - '0');
+    }
+    while (isspace((uchar) *p))                // skip trailing space
+        p++;
+    if (*p == '\0')
+        is_ok = true;
+bye:
+    if (ok)
+        *ok = is_ok;
+    return is_ok ? val : 0;
+}
+
+/*!
+    Returns the string converted to a \c{short} value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, is out of range, or if it has trailing garbage; otherwise
+    *\a ok is set to true.
+*/
+
+short Q3CString::toShort(bool *ok) const
+{
+    long v = toLong(ok);
+    if (ok && *ok && (v < -32768 || v > 32767))
+        *ok = false;
+    return (short)v;
+}
+
+/*!
+    Returns the string converted to an \c{unsigned short} value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, is out of range, or if it has trailing garbage; otherwise
+    *\a ok is set to true.
+*/
+
+ushort Q3CString::toUShort(bool *ok) const
+{
+    ulong v = toULong(ok);
+    if (ok && *ok && (v > 65535))
+        *ok = false;
+    return (ushort)v;
+}
+
+
+/*!
+    Returns the string converted to a \c{int} value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, or if it has trailing garbage; otherwise *\a ok is set to
+    true.
+*/
+
+int Q3CString::toInt(bool *ok) const
+{
+    return (int)toLong(ok);
+}
+
+/*!
+    Returns the string converted to an \c{unsigned int} value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, or if it has trailing garbage; otherwise *\a ok is set to
+    true.
+*/
+
+uint Q3CString::toUInt(bool *ok) const
+{
+    return (uint)toULong(ok);
+}
+
+/*!
+    Returns the string converted to a \c{double} value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, or if it has trailing garbage; otherwise *\a ok is set to
+    true.
+*/
+
+double Q3CString::toDouble(bool *ok) const
+{
+    char *end;
+    double val = strtod(constData() ? constData() : "", &end);
+    if (ok)
+        *ok = (constData() && *constData() && (end == 0 || *end == '\0'));
+    return val;
+}
+
+/*!
+    Returns the string converted to a \c{float} value.
+
+    If \a ok is not 0: *\a ok is set to false if the string is not a
+    number, or if it has trailing garbage; otherwise *\a ok is set to
+    true.
+*/
+
+float Q3CString::toFloat(bool *ok) const
+{
+    return (float)toDouble(ok);
+}
+
+
+/*! \fn Q3CString &Q3CString::setStr(const char *str)
+    Makes a deep copy of \a str. Returns a reference to the string.
+*/
+
+/*!
+    \overload
+
+    Sets the string to the string representation of the number \a n
+    and returns a reference to the string.
+*/
+
+Q3CString &Q3CString::setNum(long n)
+{
+    data();
+    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 = '-';
+    *this = p;
+    return *this;
+}
+
+/*!
+    \overload
+
+    Sets the string to the string representation of the number \a n
+    and returns a reference to the string.
+*/
+
+Q3CString &Q3CString::setNum(ulong n)
+{
+    data();
+    char buf[20];
+    register char *p = &buf[19];
+    *p = '\0';
+    do {
+        *--p = ((int)(n%10)) + '0';
+        n /= 10;
+    } while (n);
+    *this = p;
+    return *this;
+}
+
+/*!
+    \fn Q3CString &Q3CString::setNum(int n)
+    \overload
+
+    Sets the string to the string representation of the number \a n
+    and returns a reference to the string.
+*/
+
+/*!
+    \fn Q3CString &Q3CString::setNum(uint n)
+    \overload
+
+    Sets the string to the string representation of the number \a n
+    and returns a reference to the string.
+*/
+
+/*!
+    \fn Q3CString &Q3CString::setNum(short n)
+    \overload
+
+    Sets the string to the string representation of the number \a n
+    and returns a reference to the string.
+*/
+
+/*!
+    \fn Q3CString &Q3CString::setNum(ushort n)
+    \overload
+
+    Sets the string to the string representation of the number \a n
+    and returns a reference to the string.
+*/
+
+/*!
+    Sets the string to the string representation of the number \a n
+    and returns a reference to the string.
+
+    The format of the string representation is specified by the format
+    character \a f, and the precision (number of digits after the
+    decimal point) is specified with \a prec.
+
+    The valid formats for \a f are 'e', 'E', 'f', 'g' and 'G'. The
+    formats are the same as for sprintf(); they are explained in \l
+    QString::arg().
+*/
+
+Q3CString &Q3CString::setNum(double n, char f, int prec)
+{
+#ifndef QT_NO_DEBUG
+    if (!(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G'))
+        qWarning("Q3CString::setNum: Invalid format char '%c'", f);
+#endif
+    char format[20];
+    register char *fs = format;                        // generate format string
+    *fs++ = '%';                                //   "%.<prec>l<f>"
+    if (prec > 99)
+        prec = 99;
+    *fs++ = '.';
+    if (prec >= 10) {
+        *fs++ = prec / 10 + '0';
+        *fs++ = prec % 10 + '0';
+    } else {
+        *fs++ = prec + '0';
+    }
+    *fs++ = 'l';
+    *fs++ = f;
+    *fs = '\0';
+    return sprintf(format, n);
+}
+
+/*! \fn Q3CString &Q3CString::setNum(float n, char f, int prec)
+    \overload
+*/
+
+/*!
+    Sets the character at position \a index to \a c and expands the
+    string if necessary, padding with spaces.
+
+    Returns false if \a index was out of range and the string could
+    not be expanded; otherwise returns true.
+*/
+
+bool Q3CString::setExpand(uint index, char c)
+{
+    uint oldlen = length();
+    if (index >= oldlen) {
+        resize(index+1);
+        if (index > oldlen)
+            memset(data() + oldlen, ' ', index - oldlen);
+    }
+    *(data() + index) = c;
+    return true;
+}
+
+
+/*
+    \fn Q3CString::operator const char *() const
+
+    Returns the string data.
+*/
+
+
+/*!
+    \fn Q3CString& Q3CString::append(const char *str)
+
+    Appends string \a str to the string and returns a reference to the
+    string. Equivalent to operator+=().
+*/
+
+
+
+#ifndef QT_NO_DATASTREAM
+/*! \fn QDataStream &operator<<(QDataStream &s, const Q3CString &str)
+    \relates Q3CString
+
+    Writes string \a str to the stream \a s.
+
+    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator<<(QDataStream &d, const Q3CString &s)
+{
+    if (d.version() >= QDataStream::Qt_4_0)
+        return operator<<(d, static_cast<const QByteArray &>(s));
+
+    // we need to add a NUL to keep compatibility with Qt 3's QByteArray
+    QByteArray copy = s;
+    copy.append('\0');
+    return operator<<(d, copy);
+}
+
+/*!
+  \fn QDataStream &operator>>(QDataStream &s, Q3CString &str)
+    \relates Q3CString
+
+    Reads a string into \a str from the stream \a s.
+
+    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator>>(QDataStream &d, Q3CString &s) {
+    operator>>(d, static_cast<QByteArray &>(s));
+    if (d.version() < QDataStream::Qt_4_0 && s.endsWith('\0'))
+        s.chop(1);                  // ending NUL
+    return d;
+}
+#endif
+
+/*****************************************************************************
+  Documentation for related functions
+ *****************************************************************************/
+
+/*!
+    \fn bool operator==(const Q3CString &s1, const Q3CString &s2)
+
+    \relates Q3CString
+
+    Returns true if \a s1 and \a s2 are equal; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) == 0.
+*/
+
+/*!
+    \fn bool operator==(const Q3CString &s1, const char *s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 and \a s2 are equal; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) == 0.
+*/
+
+/*!
+    \fn bool operator==(const char *s1, const Q3CString &s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 and \a s2 are equal; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) == 0.
+*/
+
+/*!
+    \fn bool operator!=(const Q3CString &s1, const Q3CString &s2)
+
+    \relates Q3CString
+
+    Returns true if \a s1 and \a s2 are different; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) != 0.
+*/
+
+/*!
+    \fn bool operator!=(const Q3CString &s1, const char *s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 and \a s2 are different; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) != 0.
+*/
+
+/*!
+    \fn bool operator!=(const char *s1, const Q3CString &s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 and \a s2 are different; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) != 0.
+*/
+
+/*!
+    \fn bool operator<(const Q3CString &s1, const char *s2)
+
+    \relates Q3CString
+
+    Returns true if \a s1 is less than \a s2; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \< 0.
+*/
+
+/*!
+    \fn bool operator<(const char *s1, const Q3CString &s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 is less than \a s2; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \< 0.
+*/
+
+/*!
+    \fn bool operator<=(const Q3CString &s1, const char *s2)
+
+    \relates Q3CString
+
+    Returns true if \a s1 is less than or equal to \a s2; otherwise
+    returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \<= 0.
+*/
+
+/*!
+    \fn bool operator<=(const char *s1, const Q3CString &s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 is less than or equal to \a s2; otherwise
+    returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \<= 0.
+*/
+
+/*!
+    \fn bool operator>(const Q3CString &s1, const char *s2)
+
+    \relates Q3CString
+
+    Returns true if \a s1 is greater than \a s2; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \> 0.
+*/
+
+/*!
+    \fn bool operator>(const char *s1, const Q3CString &s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 is greater than \a s2; otherwise returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \> 0.
+*/
+
+/*!
+    \fn bool operator>=(const Q3CString &s1, const char *s2)
+
+    \relates Q3CString
+
+    Returns true if \a s1 is greater than or equal to \a s2; otherwise
+    returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \>= 0.
+*/
+
+/*!
+    \fn bool operator>=(const char *s1, const Q3CString &s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns true if \a s1 is greater than or equal to \a s2; otherwise
+    returns false.
+
+    Equivalent to qstrcmp(\a s1, \a s2) \>= 0.
+*/
+
+/*!
+    \fn const Q3CString operator+(const Q3CString &s1, const Q3CString &s2)
+
+    \relates Q3CString
+
+    Returns a string which consists of the concatenation of \a s1 and
+    \a s2.
+*/
+
+/*!
+    \fn const Q3CString operator+(const Q3CString &s1, const char *s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns a string which consists of the concatenation of \a s1 and \a s2.
+*/
+
+/*!
+    \fn const Q3CString operator+(const char *s1, const Q3CString &s2)
+    \overload
+
+    \relates Q3CString
+
+    Returns a string which consists of the concatenation of \a s1 and \a s2.
+*/
+
+/*!
+    \fn const Q3CString operator+(const Q3CString &s, char c)
+    \overload
+
+    \relates Q3CString
+
+    Returns a string which consists of the concatenation of \a s and \a c.
+*/
+
+/*!
+    \fn const Q3CString operator+(char c, const Q3CString &s)
+    \overload
+
+    \relates Q3CString
+    Returns a string which consists of the concatenation of \a c and \a s.
+*/
+
+QT_END_NAMESPACE