src/corelib/tools/qstring.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtCore module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qstringlist.h"
00025 #include "qregexp.h"
00026 #include "qunicodetables_p.h"
00027 #ifndef QT_NO_TEXTCODEC
00028 #include <qtextcodec.h>
00029 #endif
00030 #include <qdatastream.h>
00031 #include <qlist.h>
00032 #include "qlocale.h"
00033 #include "qlocale_p.h"
00034 #include "qstringmatcher.h"
00035 #include "qtools_p.h"
00036 #include "qhash.h"
00037 #include "qdebug.h"
00038 
00039 #include <limits.h>
00040 #include <string.h>
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <stdarg.h>
00044 
00045 #ifdef truncate
00046 #undef truncate
00047 #endif
00048 
00049 #ifndef LLONG_MAX
00050 #define LLONG_MAX qint64_C(9223372036854775807)
00051 #endif
00052 #ifndef LLONG_MIN
00053 #define LLONG_MIN (-LLONG_MAX - qint64_C(1))
00054 #endif
00055 #ifndef ULLONG_MAX
00056 #define ULLONG_MAX quint64_C(18446744073709551615)
00057 #endif
00058 
00059 
00060 #ifndef QT_NO_TEXTCODEC
00061 QTextCodec *QString::codecForCStrings;
00062 #endif
00063 
00064 #ifdef QT3_SUPPORT
00065 static QHash<void *, QByteArray> *asciiCache = 0;
00066 #endif
00067 
00068 static int ucstrcmp(const QString &as, const QString &bs)
00069 {
00070     const QChar *a = as.unicode();
00071     const QChar *b = bs.unicode();
00072     if (a == b)
00073         return 0;
00074     int l = qMin(as.length(),bs.length());
00075     while (l-- && *a == *b)
00076         a++,b++;
00077     if (l == -1)
00078         return (as.length()-bs.length());
00079     return a->unicode() - b->unicode();
00080 }
00081 
00082 static int ucstricmp(const QString &as, const QString &bs)
00083 {
00084     const QChar *a = as.unicode();
00085     const QChar *b = bs.unicode();
00086     if (a == b)
00087         return 0;
00088     if (a == 0)
00089         return 1;
00090     if (b == 0)
00091         return -1;
00092     int l=qMin(as.length(),bs.length());
00093     while (l-- && QUnicodeTables::lower(*a) == QUnicodeTables::lower(*b))
00094         a++,b++;
00095     if (l==-1)
00096         return (as.length()-bs.length());
00097     return QUnicodeTables::lower(*a).unicode() - QUnicodeTables::lower(*b).unicode();
00098 }
00099 
00100 static int ucstrncmp(const QChar *a, const QChar *b, int l)
00101 {
00102     while (l-- && *a == *b)
00103         a++,b++;
00104     if (l==-1)
00105         return 0;
00106     return a->unicode() - b->unicode();
00107 }
00108 
00109 static int ucstrnicmp(const QChar *a, const QChar *b, int l)
00110 {
00111     while (l-- && QUnicodeTables::lower(*a) == QUnicodeTables::lower(*b))
00112         a++,b++;
00113     if (l==-1)
00114         return 0;
00115     return QUnicodeTables::lower(*a).unicode() - QUnicodeTables::lower(*b).unicode();
00116 }
00117 
00118 
00119 inline bool qIsUpper(char ch)
00120 {
00121     return ch >= 'A' && ch <= 'Z';
00122 }
00123 
00124 inline bool qIsDigit(char ch)
00125 {
00126     return ch >= '0' && ch <= '9';
00127 }
00128 
00129 inline char qToLower(char ch)
00130 {
00131     if (ch >= 'A' && ch <= 'Z')
00132         return ch - 'A' + 'a';
00133     else
00134         return ch;
00135 }
00136 
00137 const QString::Null QString::null = QString::Null();
00138 
00501 QString::Data QString::shared_null = { Q_ATOMIC_INIT(1), 0, 0, shared_null.array, 0, 0, 0, 0, 0, {0} };
00502 QString::Data QString::shared_empty = { Q_ATOMIC_INIT(1), 0, 0, shared_empty.array, 0, 0, 0, 0, 0, {0} };
00503 
00504 inline int QString::grow(int size)
00505 {
00506     return qAllocMore(size * sizeof(QChar), sizeof(Data)) / sizeof(QChar);
00507 }
00508 
00628 QString QString::fromWCharArray(const wchar_t *string, int size)
00629 {
00630     if (sizeof(wchar_t) == sizeof(QChar)) {
00631         return fromUtf16((ushort *)string, size);
00632     } else {
00633         return fromUcs4((uint *)string, size);
00634     }
00635 }
00636 
00669 int QString::toWCharArray(wchar_t *array) const
00670 {
00671     if (sizeof(wchar_t) == sizeof(QChar)) {
00672         memcpy(array, utf16(), sizeof(wchar_t)*length());
00673         return length();
00674     } else {
00675         wchar_t *a = array;
00676         const unsigned short *uc = utf16();
00677         for (int i = 0; i < length(); ++i) {
00678             uint u = uc[i];
00679             if (u >= 0xd800 && u < 0xdc00 && i < length()-1) {
00680                 ushort low = uc[i+1];
00681                 if (low >= 0xdc00 && low < 0xe000) {
00682                     ++i;
00683                     u = (u - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
00684                 }
00685             }
00686             *a = wchar_t(u);
00687             ++a;
00688         }
00689         return a - array;
00690     }
00691 }
00692 
00711 QString::QString(const QChar *unicode, int size)
00712 {
00713    if (!unicode) {
00714         d = &shared_null;
00715         d->ref.ref();
00716     } else if (size <= 0) {
00717         d = &shared_empty;
00718         d->ref.ref();
00719     } else {
00720         d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
00721         d->ref.init(1);
00722         d->alloc = d->size = size;
00723         d->clean = d->asciiCache = d->simpletext = d->righttoleft = 0;
00724         d->data = d->array;
00725         memcpy(d->array, unicode, size * sizeof(QChar));
00726         d->array[size] = '\0';
00727     }
00728 }
00729 
00730 
00737 QString::QString(int size, QChar ch)
00738 {
00739    if (size <= 0) {
00740         d = &shared_empty;
00741         d->ref.ref();
00742     } else {
00743         d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
00744         d->ref.init(1);
00745         d->alloc = d->size = size;
00746         d->clean = d->asciiCache = d->simpletext = d->righttoleft = 0;
00747         d->data = d->array;
00748         d->array[size] = '\0';
00749         ushort *i = d->array + size;
00750         ushort *b = d->array;
00751         const ushort value = ch.unicode();
00752         while (i != b)
00753            *--i = value;
00754     }
00755 }
00756 
00767 QString::QString(QChar ch)
00768 {
00769     d = (Data *)qMalloc(sizeof(Data) + sizeof(QChar));
00770     d->ref.init(1);
00771     d->alloc = d->size = 1;
00772     d->clean = d->asciiCache = d->simpletext = d->righttoleft = 0;
00773     d->data = d->array;
00774     d->array[0] = ch.unicode();
00775     d->array[1] = '\0';
00776 }
00777 
00818 void QString::free(Data *d)
00819 {
00820 #ifdef QT3_SUPPORT
00821     if (d->asciiCache) {
00822         Q_ASSERT(asciiCache);
00823         asciiCache->remove(d);
00824     }
00825 #endif
00826     qFree(d);
00827 }
00828 
00866 void QString::resize(int size)
00867 {
00868     if (size <= 0) {
00869         Data *x = &shared_empty;
00870         x->ref.ref();
00871         x = qAtomicSetPtr(&d, x);
00872         if (!x->ref.deref())
00873             free(x);
00874     } else {
00875         if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
00876             realloc(grow(size));
00877         if (d->alloc >= size) {
00878             d->size = size;
00879             if (d->data == d->array) {
00880                 d->array[size] = '\0';
00881             }
00882         }
00883     }
00884 }
00885 
00939 void QString::realloc(int alloc)
00940 {
00941     if (d->ref != 1 || d->data != d->array) {
00942         Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar)));
00943         if (!x)
00944             return;
00945         x->size = qMin(alloc, d->size);
00946         ::memcpy(x->array, d->data, x->size * sizeof(QChar));
00947         x->array[x->size] = 0;
00948         x->asciiCache = 0;
00949         x->ref.init(1);
00950         x->alloc = alloc;
00951         x->clean = d->clean;
00952         x->simpletext = d->simpletext;
00953         x->righttoleft = d->righttoleft;
00954         x->data = x->array;
00955         x = qAtomicSetPtr(&d, x);
00956         if (!x->ref.deref())
00957             free(x);
00958     } else {
00959 #ifdef QT3_SUPPORT
00960         if (d->asciiCache) {
00961             Q_ASSERT(asciiCache);
00962             asciiCache->remove(d);
00963         }
00964 #endif
00965         Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)));
00966         if (!x)
00967             return;
00968         x->alloc = alloc;
00969         x->data = x->array;
00970         d = x;
00971     }
00972 }
00973 
00974 void QString::realloc()
00975 {
00976     realloc(d->size);
00977 }
00978 
00979 void QString::expand(int i)
00980 {
00981     int sz = d->size;
00982     resize(qMax(i + 1, sz));
00983     if (d->size - 1 > sz) {
00984         ushort *n = d->data + d->size - 1;
00985         ushort *e = d->data + sz;
00986         while (n != e)
00987            * --n = ' ';
00988     }
00989 }
00990 
01004 QString &QString::operator=(const QString &other)
01005 {
01006     Data *x = other.d;
01007     x->ref.ref();
01008     x = qAtomicSetPtr(&d, x);
01009     if (!x->ref.deref())
01010         free(x);
01011     return *this;
01012 }
01013 
01014 
01066 QString &QString::operator=(QChar ch)
01067 {
01068     return operator=(QString(ch));
01069 }
01070 
01097 QString &QString::insert(int i, const QLatin1String &str)
01098 {
01099     const uchar *s = (const uchar *)str.latin1();
01100     if (i < 0 || !s || !(*s))
01101         return *this;
01102 
01103     int len = qstrlen(str.latin1());
01104     expand(qMax(d->size, i) + len - 1);
01105 
01106     ::memmove(d->data + i + len, d->data + i, (d->size - i - len) * sizeof(QChar));
01107     for (int j = 0; j < len; ++j)
01108         d->data[i + j] = s[j];
01109     return *this;
01110 }
01111 
01119 QString& QString::insert(int i, const QChar *unicode, int size)
01120 {
01121     if (i < 0 || size <= 0)
01122         return *this;
01123 
01124     const ushort *s = (const ushort *)unicode;
01125     if (s >= d->data && s < d->data + d->alloc) {
01126         // Part of me - take a copy
01127         ushort *tmp = static_cast<ushort *>(malloc(size * sizeof(QChar)));
01128         memcpy(tmp, s, size * sizeof(QChar));
01129         insert(i, reinterpret_cast<const QChar *>(tmp), size);
01130         ::free(tmp);
01131         return *this;
01132     }
01133 
01134     expand(qMax(d->size, i) + size - 1);
01135 
01136     ::memmove(d->data + i + size, d->data + i, (d->size - i - size) * sizeof(QChar));
01137     memcpy(d->data + i, s, size * sizeof(QChar));
01138     return *this;
01139 }
01140 
01148 QString& QString::insert(int i, QChar ch)
01149 {
01150     if (i < 0)
01151         i += d->size;
01152     if (i < 0)
01153         return *this;
01154     expand(qMax(i, d->size));
01155     ::memmove(d->data + i + 1, d->data + i, (d->size - i) * sizeof(QChar));
01156     d->data[i] = ch.unicode();
01157     return *this;
01158 }
01159 
01182 QString &QString::append(const QString &str)
01183 {
01184     if (str.d != &shared_null) {
01185         if (d == &shared_null) {
01186             operator=(str);
01187         } else {
01188             if (d->ref != 1 || d->size + str.d->size > d->alloc)
01189                 realloc(grow(d->size + str.d->size));
01190             memcpy(d->data + d->size, str.d->data, str.d->size * sizeof(QChar));
01191             d->size += str.d->size;
01192             d->data[d->size] = '\0';
01193         }
01194     }
01195     return *this;
01196 }
01197 
01202 QString &QString::append(const QLatin1String &str)
01203 {
01204     const uchar *s = (const uchar *)str.latin1();
01205     if (s) {
01206         int len = qstrlen((char *)s);
01207         if (d->ref != 1 || d->size + len > d->alloc)
01208             realloc(grow(d->size + len));
01209         ushort *i = d->data + d->size;
01210         while ((*i++ = *s++))
01211             ;
01212         d->size += len;
01213     }
01214     return *this;
01215 }
01216 
01248 QString &QString::append(QChar ch)
01249 {
01250     if (d->ref != 1 || d->size + 1 > d->alloc)
01251         realloc(grow(d->size + 1));
01252     d->data[d->size++] = ch.unicode();
01253     d->data[d->size] = '\0';
01254     return *this;
01255 }
01256 
01330 QString &QString::remove(int pos, int len)
01331 {
01332     if (pos < 0)
01333         pos += d->size;
01334     if (pos < 0 || pos >= d->size) {
01335         // range problems
01336     } else if (pos + len >= d->size) {  // pos ok
01337         resize(pos);
01338     } else if (len > 0) {
01339         detach();
01340         memmove(d->data + pos, d->data + pos + len,
01341                 (d->size - pos - len + 1) * sizeof(ushort));
01342         d->size -= len;
01343     }
01344     return *this;
01345 }
01346 
01359 QString &QString::remove(const QString &str, Qt::CaseSensitivity cs)
01360 {
01361     if (str.d->size) {
01362         int i = 0;
01363         while ((i = indexOf(str, i, cs)) != -1)
01364             remove(i, str.d->size);
01365     }
01366     return *this;
01367 }
01368 
01388 QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
01389 {
01390     int i = 0;
01391     if (cs == Qt::CaseSensitive) {
01392         while (i < d->size)
01393             if (*((const QChar*)d->data + i) == ch)
01394                 remove(i, 1);
01395             else
01396                 i++;
01397     } else {
01398         ch = QUnicodeTables::lower(ch);
01399         while (i < d->size)
01400             if (QUnicodeTables::lower(*((const QChar*)d->data + i)) == ch)
01401                 remove(i, 1);
01402             else
01403                 i++;
01404     }
01405     return *this;
01406 }
01407 
01439 QString &QString::replace(int pos, int len, const QString &after)
01440 {
01441     QString copy = after;
01442     remove(pos, len);
01443     return insert(pos, copy.constData(), copy.d->size);
01444 }
01445 
01453 QString &QString::replace(int pos, int len, const QChar *unicode, int size)
01454 {
01455     remove(pos, len);
01456     return insert(pos, unicode, size);
01457 }
01458 
01466 QString &QString::replace(int pos, int len, QChar after)
01467 {
01468     remove(pos, len);
01469     return insert(pos, after);
01470 }
01471 
01487 QString &QString::replace(const QString &before, const QString &after, Qt::CaseSensitivity cs)
01488 {
01489     if (d->size == 0) {
01490         if (before.d->size)
01491             return *this;
01492     } else {
01493         if (cs == Qt::CaseSensitive && before == after)
01494             return *this;
01495     }
01496     if (d->ref != 1)
01497         realloc(d->size);
01498 
01499     QStringMatcher matcher(before, cs);
01500     int index = 0;
01501     const int bl = before.d->size;
01502     const int al = after.d->size;
01503 
01504     if (bl == al) {
01505         if (bl) {
01506             const QChar *auc = (const QChar*) after.d->data;
01507             while ((index = matcher.indexIn(*this, index)) != -1) {
01508                 // we need memmove(), not memcpy(), in the rare case where
01509                 // this == &after, before == after, and cs is Qt::CaseInsensitive
01510                 memmove(d->data + index, auc, al * sizeof(QChar));
01511                 index += bl;
01512             }
01513         }
01514     } else if (al < bl) {
01515         const QChar *auc = after.unicode();
01516         uint to = 0;
01517         uint movestart = 0;
01518         uint num = 0;
01519         while ((index = matcher.indexIn(*this, index)) != -1) {
01520             if (num) {
01521                 int msize = index - movestart;
01522                 if (msize > 0) {
01523                     memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
01524                     to += msize;
01525                 }
01526             } else {
01527                 to = index;
01528             }
01529             if (al) {
01530                 memcpy(d->data+to, auc, al*sizeof(QChar));
01531                 to += al;
01532             }
01533             index += bl;
01534             movestart = index;
01535             num++;
01536         }
01537         if (num) {
01538             int msize = d->size - movestart;
01539             if (msize > 0)
01540                 memmove(d->data + to, d->data + movestart, msize * sizeof(QChar));
01541             resize(d->size - num*(bl-al));
01542         }
01543     } else {
01544         const QString copy = after;
01545 
01546         // the most complex case. We don't want to lose performance by doing repeated
01547         // copies and reallocs of the string.
01548         while (index != -1) {
01549             uint indices[4096];
01550             uint pos = 0;
01551             while (pos < 4095) {
01552                 index = matcher.indexIn(*this, index);
01553                 if (index == -1)
01554                     break;
01555                 indices[pos++] = index;
01556                 index += bl;
01557                 // avoid infinite loop
01558                 if (!bl)
01559                     index++;
01560             }
01561             if (!pos)
01562                 break;
01563 
01564             // we have a table of replacement positions, use them for fast replacing
01565             int adjust = pos*(al-bl);
01566             // index has to be adjusted in case we get back into the loop above.
01567             if (index != -1)
01568                 index += adjust;
01569             int newLen = d->size + adjust;
01570             int moveend = d->size;
01571             if (newLen > d->size)
01572                 resize(newLen);
01573 
01574             while (pos) {
01575                 pos--;
01576                 int movestart = indices[pos] + bl;
01577                 int insertstart = indices[pos] + pos*(al-bl);
01578                 int moveto = insertstart + al;
01579                 memmove(d->data + moveto, d->data + movestart, (moveend - movestart)*sizeof(QChar));
01580                 memcpy(d->data + insertstart, copy.unicode(), al*sizeof(QChar));
01581                 moveend = movestart-bl;
01582             }
01583         }
01584     }
01585     return *this;
01586 }
01587 
01597 QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs)
01598 {
01599     return replace(QString(ch), after, cs);
01600 }
01601 
01610 QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs)
01611 {
01612     if (d->size) {
01613         QChar *i = data();
01614         QChar *e = i + d->size;
01615         if (cs == Qt::CaseSensitive) {
01616             for (; i != e; ++i)
01617                 if (*i == before)
01618                    * i = after;
01619         } else {
01620             before = QUnicodeTables::lower(before);
01621             for (; i != e; ++i)
01622                 if (QUnicodeTables::lower(*i) == before)
01623                    * i = after;
01624         }
01625     }
01626     return *this;
01627 }
01628 
01638 bool QString::operator==(const QString &other) const
01639 {
01640     return (size() == other.size()) &&
01641         (memcmp((char*)unicode(),(char*)other.unicode(), size()*sizeof(QChar))==0);
01642 }
01643 
01647 bool QString::operator==(const QLatin1String &other) const
01648 {
01649     const ushort *uc = d->data;
01650     const ushort *e = uc + d->size;
01651     const uchar *c = (uchar *)other.latin1();
01652 
01653     if (!c)
01654         return isEmpty();
01655 
01656     while (*c) {
01657         if (uc == e || *uc != *c)
01658             return false;
01659         ++uc;
01660         ++c;
01661     }
01662     return (uc == e);
01663 }
01664 
01700 bool QString::operator<(const QString &other) const
01701 {
01702     return ucstrcmp(*this, other) < 0;
01703 }
01704 
01708 bool QString::operator<(const QLatin1String &other) const
01709 {
01710     const ushort *uc = d->data;
01711     const ushort *e = uc + d->size;
01712     const uchar *c = (uchar *) other.latin1();
01713 
01714     if (!c || *c == 0)
01715         return false;
01716 
01717     while (*c) {
01718         if (uc == e || *uc != *c)
01719             break;
01720         ++uc;
01721         ++c;
01722     }
01723     return (uc == e ? *c : *uc < *c);
01724 }
01725 
01808 bool QString::operator>(const QLatin1String &other) const
01809 {
01810     const ushort *uc = d->data;;
01811     const ushort *e = uc + d->size;
01812     const uchar *c = (uchar *) other.latin1();
01813 
01814     if (!c || *c == '\0')
01815         return !isEmpty();
01816 
01817     while (*c) {
01818         if (uc == e || *uc != *c)
01819             break;
01820         ++uc;
01821         ++c;
01822     }
01823     return (uc == e ? false : *uc > *c);
01824 }
01825 
01936 #define REHASH(a) \
01937     if (sl_minus_1 < (int)sizeof(int) * CHAR_BIT)       \
01938         hashHaystack -= (a) << sl_minus_1; \
01939     hashHaystack <<= 1
01940 
01961 int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
01962 {
01963     const int l = d->size;
01964     const int sl = str.d->size;
01965     if (from < 0)
01966         from += l;
01967     if (uint(sl + from) > (uint)l)
01968         return -1;
01969     if (!sl)
01970         return from;
01971     if (!l)
01972         return -1;
01973 
01974     if (sl == 1)
01975         return indexOf(*(const QChar *)str.d->data, from, cs);
01976 
01977     /*
01978         We use the Boyer-Moore algorithm in cases where the overhead
01979         for the skip table should pay off, otherwise we use a simple
01980         hash function.
01981     */
01982     if (l > 500 && sl > 5)
01983         return QStringMatcher(str, cs).indexIn(*this, from);
01984 
01985     /*
01986         We use some hashing for efficiency's sake. Instead of
01987         comparing strings, we compare the hash value of str with that
01988         of a part of this QString. Only if that matches, we call
01989         ucstrncmp() or ucstrnicmp().
01990     */
01991     const QChar *needle = (const QChar*) str.d->data;
01992     const QChar *haystack = (const QChar*) d->data + from;
01993     const QChar *end = (const QChar*) d->data + (l-sl);
01994     const int sl_minus_1 = sl-1;
01995     int hashNeedle = 0, hashHaystack = 0, idx;
01996 
01997     if (cs == Qt::CaseSensitive) {
01998         for (idx = 0; idx < sl; ++idx) {
01999             hashNeedle = ((hashNeedle<<1) + needle[idx].unicode());
02000             hashHaystack = ((hashHaystack<<1) + haystack[idx].unicode());
02001         }
02002         hashHaystack -= (haystack+sl_minus_1)->unicode();
02003 
02004         while (haystack <= end) {
02005             hashHaystack += (haystack+sl_minus_1)->unicode();
02006             if (hashHaystack == hashNeedle
02007                  && ucstrncmp(needle, haystack, sl) == 0)
02008                 return haystack-unicode();
02009 
02010             REHASH(haystack->unicode());
02011             ++haystack;
02012         }
02013     } else {
02014         for (idx = 0; idx < sl; ++idx) {
02015             hashNeedle = ((hashNeedle<<1) +
02016                           QUnicodeTables::lower(needle[idx].unicode()));
02017             hashHaystack = ((hashHaystack<<1) +
02018                             QUnicodeTables::lower(haystack[idx].unicode()));
02019         }
02020 
02021         hashHaystack -= QUnicodeTables::lower(*(haystack+sl_minus_1)).unicode();
02022         while (haystack <= end) {
02023             hashHaystack += QUnicodeTables::lower(*(haystack+sl_minus_1)).unicode();
02024             if (hashHaystack == hashNeedle
02025                  && ucstrnicmp(needle, haystack, sl) == 0)
02026                 return haystack-unicode();
02027 
02028             REHASH(QUnicodeTables::lower(*haystack).unicode());
02029             ++haystack;
02030         }
02031     }
02032     return -1;
02033 }
02034 
02042 int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
02043 {
02044     if (from < 0)
02045         from = qMax(from + d->size, 0);
02046     if (from  < d->size) {
02047         const QChar *n = (const QChar*)d->data + from - 1;
02048         const QChar *e = (const QChar*)d->data + d->size;
02049         if (cs == Qt::CaseSensitive) {
02050             while (++n != e)
02051                 if (*n == ch)
02052                     return  n - (const QChar*)d->data;
02053         } else {
02054             ch = QUnicodeTables::lower(ch);
02055             while (++n != e)
02056                 if (QUnicodeTables::lower(*n) == ch)
02057                     return  n - (const QChar*)d->data;
02058         }
02059     }
02060     return -1;
02061 }
02062 
02082 int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
02083 {
02084     /*
02085         See indexOf() for explanations.
02086     */
02087     const int l = d->size;
02088     if (from < 0)
02089         from += l;
02090     const int sl = str.d->size;
02091     int delta = l-sl;
02092     if (from == l && sl == 0)
02093         return from;
02094     if (from < 0 || from >= l || delta < 0)
02095         return -1;
02096     if (from > delta)
02097         from = delta;
02098 
02099     if (sl == 1)
02100         return lastIndexOf(*(const QChar*) str.d->data, from, cs);
02101 
02102     const QChar *needle = (const QChar*) str.d->data;
02103     const QChar *haystack = (const QChar*) d->data + from;
02104     const QChar *end = (const QChar*) d->data;
02105     const int sl_minus_1 = sl-1;
02106     const QChar *n = needle+sl_minus_1;
02107     const QChar *h = haystack+sl_minus_1;
02108     int hashNeedle = 0, hashHaystack = 0, idx;
02109 
02110     if (cs == Qt::CaseSensitive) {
02111         for (idx = 0; idx < sl; ++idx) {
02112             hashNeedle = ((hashNeedle<<1) + (n-idx)->unicode());
02113             hashHaystack = ((hashHaystack<<1) + (h-idx)->unicode());
02114         }
02115         hashHaystack -= haystack->unicode();
02116 
02117         while (haystack >= end) {
02118             hashHaystack += haystack->unicode();
02119             if (hashHaystack == hashNeedle
02120                  && ucstrncmp(needle, haystack, sl) == 0)
02121                 return haystack-unicode();
02122             --haystack;
02123             REHASH((haystack+sl)->unicode());
02124         }
02125     } else {
02126         for (idx = 0; idx < sl; ++idx) {
02127             hashNeedle = ((hashNeedle<<1)
02128                           + QUnicodeTables::lower((n-idx)->unicode()));
02129             hashHaystack = ((hashHaystack<<1)
02130                             + QUnicodeTables::lower((h-idx)->unicode()));
02131         }
02132         hashHaystack -= QUnicodeTables::lower(*haystack).unicode();
02133 
02134         while (haystack >= end) {
02135             hashHaystack += QUnicodeTables::lower(*haystack).unicode();
02136             if (hashHaystack == hashNeedle
02137                  && ucstrnicmp(needle, haystack, sl) == 0)
02138                 return haystack-unicode();
02139             --haystack;
02140             REHASH(QUnicodeTables::lower(*(haystack+sl)).unicode());
02141         }
02142     }
02143     return -1;
02144 }
02145 
02151 int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
02152 {
02153     if (from < 0)
02154         from += d->size;
02155     if (from < 0 || from >= d->size)
02156         return -1;
02157     if (from >= 0) {
02158         const QChar *n =  (const QChar*)d->data + from;
02159         const QChar *b = (const QChar*)d->data;
02160         if (cs == Qt::CaseSensitive) {
02161             for (; n >= b; --n)
02162                 if (*n == ch)
02163                     return  n - b;
02164         } else {
02165             ch = QUnicodeTables::lower(ch);
02166             for (; n >= b; --n)
02167                 if (QUnicodeTables::lower(*n) == ch)
02168                     return  n - b;
02169         }
02170     }
02171     return -1;
02172 }
02173 
02174 #ifndef QT_NO_REGEXP
02175 
02197 QString& QString::replace(const QRegExp &rx, const QString &after)
02198 {
02199     QRegExp rx2(rx);
02200 
02201     if (isEmpty() && rx2.indexIn(*this) == -1)
02202         return *this;
02203 
02204     realloc();
02205 
02206     int index = 0;
02207     int numCaptures = rx2.numCaptures();
02208     int al = after.length();
02209     QRegExp::CaretMode caretMode = QRegExp::CaretAtZero;
02210 
02211     if (numCaptures > 0) {
02212         if (numCaptures > 9)
02213             numCaptures = 9;
02214 
02215         const QChar *uc = after.unicode();
02216         int numBackRefs = 0;
02217 
02218         for (int i = 0; i < al - 1; i++) {
02219             if (uc[i] == QLatin1Char('\\')) {
02220                 int no = uc[i + 1].digitValue();
02221                 if (no > 0 && no <= numCaptures)
02222                     numBackRefs++;
02223             }
02224         }
02225 
02226         /*
02227           This is the harder case where we have back-references.
02228           We don't try to optimize it.
02229         */
02230         if (numBackRefs > 0) {
02231             int *capturePositions = new int[numBackRefs];
02232             int *captureNumbers = new int[numBackRefs];
02233             int j = 0;
02234 
02235             for (int i = 0; i < al - 1; i++) {
02236                 if (uc[i] == QLatin1Char('\\')) {
02237                     int no = uc[i + 1].digitValue();
02238                     if (no > 0 && no <= numCaptures) {
02239                         capturePositions[j] = i;
02240                         captureNumbers[j] = no;
02241                         j++;
02242                     }
02243                 }
02244             }
02245 
02246             while (index <= length()) {
02247                 index = rx2.indexIn(*this, index, caretMode);
02248                 if (index == -1)
02249                     break;
02250 
02251                 QString after2 = after;
02252                 for (j = numBackRefs - 1; j >= 0; j--)
02253                     after2.replace(capturePositions[j], 2,
02254                                     rx2.cap(captureNumbers[j]));
02255 
02256                 replace(index, rx2.matchedLength(), after2);
02257                 index += after2.length();
02258 
02259                 if (rx2.matchedLength() == 0) {
02260                     // avoid infinite loop on 0-length matches (e.g., [a-z]*)
02261                     index++;
02262                 }
02263                 caretMode = QRegExp::CaretWontMatch;
02264             }
02265             delete[] capturePositions;
02266             delete[] captureNumbers;
02267             return *this;
02268         }
02269     }
02270 
02271     /*
02272       This is the simple and optimized case where we don't have
02273       back-references.
02274    */
02275     while (index != -1) {
02276         struct {
02277             int pos;
02278             int length;
02279         } replacements[2048];
02280 
02281         int pos = 0;
02282         int adjust = 0;
02283         while (pos < 2047) {
02284             index = rx2.indexIn(*this, index, caretMode);
02285             if (index == -1)
02286                 break;
02287             int ml = rx2.matchedLength();
02288             replacements[pos].pos = index;
02289             replacements[pos++].length = ml;
02290             index += ml;
02291             adjust += al - ml;
02292             // avoid infinite loop
02293             if (!ml)
02294                 index++;
02295         }
02296         if (!pos)
02297             break;
02298         replacements[pos].pos = d->size;
02299         int newlen = d->size + adjust;
02300 
02301         // to continue searching at the right position after we did
02302         // the first round of replacements
02303         if (index != -1)
02304             index += adjust;
02305         QString newstring;
02306         newstring.reserve(newlen + 1);
02307         QChar *newuc = newstring.data();
02308         QChar *uc = newuc;
02309         int copystart = 0;
02310         int i = 0;
02311         while (i < pos) {
02312             int copyend = replacements[i].pos;
02313             int size = copyend - copystart;
02314             memcpy(uc, d->data + copystart, size * sizeof(QChar));
02315             uc += size;
02316             memcpy(uc, after.d->data, al * sizeof(QChar));
02317             uc += al;
02318             copystart = copyend + replacements[i].length;
02319             i++;
02320         }
02321         memcpy(uc, d->data + copystart, (d->size - copystart) * sizeof(QChar));
02322         newstring.resize(newlen);
02323         *this = newstring;
02324         caretMode = QRegExp::CaretWontMatch;
02325     }
02326     return *this;
02327 }
02328 #endif
02329 
02339 int QString::count(const QString &str, Qt::CaseSensitivity cs) const
02340 {
02341     int num = 0;
02342     int i = -1;
02343     if (d->size > 500 && str.d->size > 5) {
02344         QStringMatcher matcher(str, cs);
02345         while ((i = matcher.indexIn(*this, i + 1)) != -1)
02346             ++num;
02347     } else {
02348         while ((i = indexOf(str, i + 1, cs)) != -1)
02349             ++num;
02350     }
02351     return num;
02352 }
02353 
02359 int QString::count(QChar ch, Qt::CaseSensitivity cs) const
02360 {
02361     int num = 0;
02362     const QChar *i = (const QChar*) d->data + d->size;
02363     const QChar *b = (const QChar*) d->data;
02364     if (cs == Qt::CaseSensitive) {
02365         while (i != b)
02366             if (*--i == ch)
02367                 ++num;
02368     } else {
02369         ch = QUnicodeTables::lower(ch);
02370         while (i != b)
02371             if (QUnicodeTables::lower(*--i) == ch)
02372                 ++num;
02373     }
02374     return num;
02375 }
02376 
02410 #ifndef QT_NO_REGEXP
02411 
02425 int QString::indexOf(const QRegExp& rx, int from) const
02426 {
02427     return rx.indexIn(*this, from);
02428 }
02429 
02444 int QString::lastIndexOf(const QRegExp& rx, int from) const
02445 {
02446     return rx.lastIndexIn(*this, from);
02447 }
02448 
02464 int QString::count(const QRegExp& rx) const
02465 {
02466     int count = 0;
02467     int index = -1;
02468     int len = length();
02469     while (index < len - 1) {                 // count overlapping matches
02470         index = rx.indexIn(*this, index + 1);
02471         if (index == -1)
02472             break;
02473         count++;
02474     }
02475     return count;
02476 }
02477 #endif // QT_NO_REGEXP
02478 
02561 QString QString::section(const QString &sep, int start, int end, SectionFlags flags) const
02562 {
02563     QStringList sections = split(sep, KeepEmptyParts,
02564                                  (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
02565     if (sections.isEmpty())
02566         return QString();
02567     if (!(flags & SectionSkipEmpty)) {
02568         if (start < 0)
02569             start += sections.count();
02570         if (end < 0)
02571             end += sections.count();
02572     } else {
02573         int skip = 0;
02574         for (int k=0; k<sections.size(); ++k) {
02575             if (sections.at(k).isEmpty())
02576                 skip++;
02577         }
02578         if (start < 0)
02579             start += sections.count() - skip;
02580         if (end < 0)
02581             end += sections.count() - skip;
02582     }
02583     int x = 0;
02584     QString ret;
02585     int first_i = start, last_i = end;
02586     for (int i = 0; x <= end && i < sections.size(); ++i) {
02587         QString section = sections.at(i);
02588         const bool empty = section.isEmpty();
02589         if (x >= start) {
02590             if(x == start)
02591                 first_i = i;
02592             if(x == end)
02593                 last_i = i;
02594             if(x > start)
02595                 ret += sep;
02596             ret += section;
02597         }
02598         if (!empty || !(flags & SectionSkipEmpty))
02599             x++;
02600     }
02601     if((flags & SectionIncludeLeadingSep) && first_i)
02602         ret.prepend(sep);
02603     if((flags & SectionIncludeTrailingSep) && last_i < sections.size()-1)
02604         ret += sep;
02605     return ret;
02606 }
02607 
02608 #ifndef QT_NO_REGEXP
02609 class qt_section_chunk {
02610 public:
02611     qt_section_chunk(int l, QString s) { length = l; string = s; }
02612     int length;
02613     QString string;
02614 };
02615 
02632 QString QString::section(const QRegExp &reg, int start, int end, SectionFlags flags) const
02633 {
02634     const QChar *uc = unicode();
02635     if(!uc)
02636         return QString();
02637 
02638     QRegExp sep(reg);
02639     sep.setCaseSensitivity((flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive
02640                                                                 : Qt::CaseSensitive);
02641 
02642     QList<qt_section_chunk> sections;
02643     int n = length(), m = 0, last_m = 0, last_len = 0;
02644     while ((m = sep.indexIn(*this, m)) != -1) {
02645         sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m)));
02646         last_m = m;
02647         last_len = sep.matchedLength();
02648         m += qMax(sep.matchedLength(), 1);
02649     }
02650     sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
02651 
02652     if(start < 0)
02653         start += sections.count();
02654     if(end < 0)
02655         end += sections.count();
02656 
02657     QString ret;
02658     int x = 0;
02659     int first_i = start, last_i = end;
02660     for (int i = 0; x <= end && i < sections.size(); ++i) {
02661         const qt_section_chunk &section = sections.at(i);
02662         const bool empty = (section.length == section.string.length());
02663         if (x >= start) {
02664             if(x == start)
02665                 first_i = i;
02666             if(x == end)
02667                 last_i = i;
02668             if(x != start)
02669                 ret += section.string;
02670             else
02671                 ret += section.string.mid(section.length);
02672         }
02673         if (!empty || !(flags & SectionSkipEmpty))
02674             x++;
02675     }
02676     if((flags & SectionIncludeLeadingSep)) {
02677         const qt_section_chunk &section = sections.at(first_i);
02678         ret.prepend(section.string.left(section.length));
02679     }
02680     if((flags & SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
02681         const qt_section_chunk &section = sections.at(last_i+1);
02682         ret += section.string.left(section.length);
02683     }
02684     return ret;
02685 }
02686 #endif
02687 
02704 QString QString::left(int len)  const
02705 {
02706     if (d == &shared_null)
02707         return QString();
02708     if (len >= d->size || len < 0)
02709         return *this;
02710     return QString((const QChar*) d->data, len);
02711 }
02712 
02729 QString QString::right(int len) const
02730 {
02731     if (d == &shared_null)
02732         return QString();
02733     if (len >= d->size || len < 0)
02734         return *this;
02735     return QString((const QChar*) d->data + d->size - len, len);
02736 }
02737 
02760 QString QString::mid(int i, int len) const
02761 {
02762     if (d == &shared_null || i >= d->size)
02763         return QString();
02764     if (len < 0)
02765         len = d->size - i;
02766     if (i < 0) {
02767         len += i;
02768         i = 0;
02769     }
02770     if (len + i > d->size)
02771         len = d->size - i;
02772     if (i == 0 && len == d->size)
02773         return *this;
02774     return QString((const QChar*) d->data + i, len);
02775 }
02776 
02791 bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const
02792 {
02793     if (d == &shared_null)
02794         return (s.d == &shared_null);
02795     if (d->size == 0)
02796         return s.d->size == 0;
02797     if (s.d->size > d->size)
02798         return false;
02799     if (cs == Qt::CaseSensitive) {
02800         return memcmp((char*)d->data, (char*)s.d->data, s.d->size*sizeof(QChar)) == 0;
02801     } else {
02802         for (int i = 0; i < s.d->size; ++i)
02803             if (QUnicodeTables::lower(d->data[i]) != QUnicodeTables::lower(s.d->data[i]))
02804                 return false;
02805     }
02806     return true;
02807 }
02808 
02812 bool QString::startsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const
02813 {
02814     if (d == &shared_null)
02815         return (s.latin1() == 0);
02816     if (d->size == 0)
02817         return !s.latin1() || *s.latin1() == 0;
02818     int slen = qstrlen(s.latin1());
02819     if (slen > d->size)
02820         return false;
02821     const uchar *latin = (const uchar *)s.latin1();
02822     if (cs == Qt::CaseSensitive) {
02823         for (int i = 0; i < slen; ++i)
02824             if (d->data[i] != latin[i])
02825                 return false;
02826     } else {
02827         for (int i = 0; i < slen; ++i)
02828             if (QUnicodeTables::lower(d->data[i]) != QUnicodeTables::lower(latin[i]))
02829                 return false;
02830     }
02831     return true;
02832 }
02833 
02840 bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const
02841 {
02842     return d->size
02843            && (cs == Qt::CaseSensitive
02844                ? d->data[0] == c
02845                : QUnicodeTables::lower(d->data[0]) == QUnicodeTables::lower(c.unicode()));
02846 }
02847 
02862 bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const
02863 {
02864     if (d == &shared_null)
02865         return (s.d == &shared_null);
02866     if (d->size == 0)
02867         return s.d->size == 0;
02868     int pos = d->size - s.d->size;
02869     if (pos < 0)
02870         return false;
02871     if (cs == Qt::CaseSensitive) {
02872         return memcmp((char*)&d->data[pos], (char*)s.d->data, s.d->size*sizeof(QChar)) == 0;
02873     } else {
02874         for (int i = 0; i < s.length(); i++)
02875             if (QUnicodeTables::lower(d->data[pos+i]) != QUnicodeTables::lower(s.d->data[i]))
02876                 return false;
02877     }
02878     return true;
02879 }
02880 
02884 bool QString::endsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const
02885 {
02886     if (d == &shared_null)
02887         return (s.latin1() == 0);
02888     if (d->size == 0)
02889         return !s.latin1() || *s.latin1() == 0;
02890     int slen = qstrlen(s.latin1());
02891     int pos = d->size - slen;
02892     const uchar *latin = (const uchar *)s.latin1();
02893     if (pos < 0)
02894         return false;
02895     if (cs == Qt::CaseSensitive) {
02896         for (int i = 0; i < slen; i++)
02897             if (d->data[pos+i] != latin[i])
02898                 return false;
02899     } else {
02900         for (int i = 0; i < slen; i++)
02901             if (QUnicodeTables::lower(d->data[pos+i]) != QUnicodeTables::lower(latin[i]))
02902                 return false;
02903     }
02904     return true;
02905 }
02906 
02913 bool QString::endsWith(const QChar &c, Qt::CaseSensitivity cs) const
02914 {
02915     return d->size
02916            && (cs == Qt::CaseSensitive
02917                ? d->data[d->size - 1] == c
02918                : QUnicodeTables::lower(d->data[d->size - 1]) == QUnicodeTables::lower(c.unicode()));
02919 }
02920 
02952 QByteArray QString::toLatin1() const
02953 {
02954     QByteArray ba;
02955     if (d->size) {
02956         ba.resize(d->size);
02957         const ushort *i = d->data;
02958         const ushort *e = d->data + d->size;
02959         uchar *s = (uchar*) ba.data();
02960         while (i != e) {
02961             *s++ = (*i>0xff) ? '?' : (uchar) *i;
02962             ++i;
02963         }
02964     }
02965     return ba;
02966 }
02967 
02977 QByteArray QString::toAscii() const
02978 {
02979 #ifndef QT_NO_TEXTCODEC
02980     if (codecForCStrings)
02981         return codecForCStrings->fromUnicode(*this);
02982 #endif // QT_NO_TEXTCODEC
02983     return toLatin1();
02984 }
02985 
02996 QByteArray QString::toLocal8Bit() const
02997 {
02998 #ifndef QT_NO_TEXTCODEC
02999     if (QTextCodec::codecForLocale())
03000         return QTextCodec::codecForLocale()->fromUnicode(*this);
03001 #endif // QT_NO_TEXTCODEC
03002     return toLatin1();
03003 }
03004 
03010 QByteArray QString::toUtf8() const
03011 {
03012     QByteArray ba;
03013     if (d->size) {
03014         int l = d->size;
03015         int rlen = l*3+1;
03016         ba.resize(rlen);
03017         uchar *cursor = (uchar*)ba.data();
03018         const ushort *ch =d->data;
03019         for (int i=0; i < l; i++) {
03020             uint u = *ch;
03021             if (u < 0x80) {
03022                 *cursor++ = (uchar)u;
03023             } else {
03024                 if (u < 0x0800) {
03025                     *cursor++ = 0xc0 | ((uchar) (u >> 6));
03026                 } else {
03027                     if (u >= 0xd800 && u < 0xdc00 && i < l-1) {
03028                         ushort low = ch[1];
03029                         if (low >= 0xdc00 && low < 0xe000) {
03030                             ++ch;
03031                             ++i;
03032                             u = (u - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
03033                         }
03034                     }
03035                     if (u > 0xffff) {
03036                         // if people are working in utf8, but strings are encoded in eg. latin1, the resulting
03037                         // name might be invalid utf8. This and the corresponding code in fromUtf8 takes care
03038                         // we can handle this without loosing information. This can happen with latin filenames
03039                         // and a utf8 locale under Unix.
03040                         if (u > 0x10fe00 && u < 0x10ff00) {
03041                             *cursor++ = (u - 0x10fe00);
03042                             ++ch;
03043                             continue;
03044                         } else {
03045                             *cursor++ = 0xf0 | ((uchar) (u >> 18));
03046                             *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f);
03047                         }
03048                     } else {
03049                         *cursor++ = 0xe0 | ((uchar) (u >> 12));
03050                     }
03051                     *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f);
03052                 }
03053                 *cursor++ = 0x80 | ((uchar) (u&0x3f));
03054             }
03055             ++ch;
03056         }
03057         ba.resize(cursor - (uchar*)ba.constData());
03058     }
03059     return ba;
03060 }
03061 
03069 QVector<uint> QString::toUcs4() const
03070 {
03071     QVector<uint> v(length());
03072     uint *a = v.data();
03073     const unsigned short *uc = utf16();
03074     for (int i = 0; i < length(); ++i) {
03075         uint u = uc[i];
03076         if (u >= 0xd800 && u < 0xdc00 && i < length()-1) {
03077             ushort low = uc[i+1];
03078             if (low >= 0xdc00 && low < 0xe000) {
03079                 ++i;
03080                 u = (u - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
03081             }
03082         }
03083         *a = u;
03084         ++a;
03085     }
03086     v.resize(a - v.data());
03087     return v;
03088 }
03089 
03090 QString::Data *QString::fromLatin1_helper(const char *str, int size)
03091 {
03092     Data *d;
03093     if (!str) {
03094         d = &shared_null;
03095         d->ref.ref();
03096     } else if (size == 0 || (!*str && size < 0)) {
03097         d = &shared_empty;
03098         d->ref.ref();
03099     } else {
03100         if (size < 0)
03101             size = qstrlen(str);
03102         d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar)));
03103         d->ref.init(1);
03104         d->alloc = d->size = size;
03105         d->clean = d->asciiCache = d->simpletext = d->righttoleft = 0;
03106         d->data = d->array;
03107         ushort *i = d->data;
03108         d->array[size] = '\0';
03109         while (size--)
03110            *i++ = (uchar)*str++;
03111     }
03112     return d;
03113 }
03114 
03115 QString::Data *QString::fromAscii_helper(const char *str, int size)
03116 {
03117 #ifndef QT_NO_TEXTCODEC
03118     if (codecForCStrings) {
03119         Data *d;
03120         if (!str) {
03121             d = &shared_null;
03122             d->ref.ref();
03123         } else if (size == 0 || (!*str && size < 0)) {
03124             d = &shared_empty;
03125             d->ref.ref();
03126         } else {
03127             if (size < 0)
03128                 size = qstrlen(str);
03129             QString s = codecForCStrings->toUnicode(str, size);
03130             d = s.d;
03131             d->ref.ref();
03132         }
03133         return d;
03134     }
03135 #endif
03136     return fromLatin1_helper(str, size);
03137 }
03138 
03148 QString QString::fromLatin1(const char *str, int size)
03149 {
03150     return QString(fromLatin1_helper(str, size), 0);
03151 }
03152 
03153 
03154 #ifdef QT3_SUPPORT
03155 
03159 const char *QString::ascii_helper() const
03160 {
03161     if (!asciiCache)
03162         asciiCache = new QHash<void *, QByteArray>();
03163 
03164     d->asciiCache = true;
03165     QByteArray ascii = toAscii();
03166     QByteArray old = asciiCache->value(d);
03167     if (old == ascii)
03168         return old.constData();
03169     asciiCache->insert(d, ascii);
03170     return ascii.constData();
03171 }
03172 
03176 const char *QString::latin1_helper() const
03177 {
03178     if (!asciiCache)
03179         asciiCache = new QHash<void *, QByteArray>();
03180 
03181     d->asciiCache = true;
03182     QByteArray ascii = toLatin1();
03183     QByteArray old = asciiCache->value(d);
03184     if (old == ascii)
03185         return old.constData();
03186     asciiCache->insert(d, ascii);
03187     return ascii.constData();
03188 }
03189 
03190 #endif
03191 
03192 #ifdef Q_OS_WIN32
03193 #include "qt_windows.h"
03194 
03195 QByteArray qt_winQString2MB(const QString& s, int uclen)
03196 {
03197     if (uclen < 0)
03198         uclen = s.length();
03199     if (s.isNull())
03200         return QByteArray();
03201     if (uclen == 0)
03202         return QByteArray("");
03203     return qt_winQString2MB(s.constData(), uclen);
03204 }
03205 
03206 QByteArray qt_winQString2MB(const QChar *ch, int uclen)
03207 {
03208     if (!ch)
03209   return QByteArray();
03210     if (uclen == 0)
03211         return QByteArray("");
03212     BOOL used_def;
03213     QByteArray mb(4096, 0);
03214     int len;
03215     while (!(len=WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)ch, uclen,
03216                 mb.data(), mb.size()-1, 0, &used_def)))
03217     {
03218         int r = GetLastError();
03219         if (r == ERROR_INSUFFICIENT_BUFFER) {
03220             mb.resize(1+WideCharToMultiByte(CP_ACP, 0,
03221                                 (const WCHAR*)ch, uclen,
03222                                 0, 0, 0, &used_def));
03223                 // and try again...
03224         } else {
03225 #ifndef QT_NO_DEBUG
03226             // Fail.
03227             qWarning("WideCharToMultiByte: Cannot convert multibyte text (error %d): %s (UTF-8)",
03228                 r, QString(ch, uclen).toLocal8Bit().data());
03229 #endif
03230             break;
03231         }
03232     }
03233     mb.resize(len);
03234     return mb;
03235 }
03236 
03237 QString qt_winMB2QString(const char *mb, int mblen)
03238 {
03239     if (!mb || !mblen)
03240         return QString();
03241     const int wclen_auto = 4096;
03242     WCHAR wc_auto[wclen_auto];
03243     int wclen = wclen_auto;
03244     WCHAR *wc = wc_auto;
03245     int len;
03246     while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
03247                 mb, mblen, wc, wclen)))
03248     {
03249         int r = GetLastError();
03250         if (r == ERROR_INSUFFICIENT_BUFFER) {
03251             if (wc != wc_auto) {
03252                 qWarning("MultiByteToWideChar: Size changed");
03253                 break;
03254             } else {
03255                 wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
03256                                     mb, mblen, 0, 0);
03257                 wc = new WCHAR[wclen];
03258                 // and try again...
03259             }
03260         } else {
03261             // Fail.
03262             qWarning("MultiByteToWideChar: Cannot convert multibyte text");
03263             break;
03264         }
03265     }
03266     if (len <= 0)
03267         return QString();
03268     if (wc[len-1] == 0) // len - 1: we don't want terminator
03269         --len;
03270     QString s((QChar*)wc, len);
03271     if (wc != wc_auto)
03272         delete [] wc;
03273     return s;
03274 }
03275 #endif // Q_OS_WIN32
03276 
03289 QString QString::fromLocal8Bit(const char *str, int size)
03290 {
03291     if (!str)
03292         return QString();
03293     if (size == 0 || (!*str && size < 0))
03294         return QLatin1String("");
03295 #if defined(Q_OS_WIN32)
03296     if(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) {
03297         return qt_winMB2QString(str, size);
03298     }
03299 #endif
03300 #if !defined(QT_NO_TEXTCODEC)
03301     if (size < 0)
03302         size = qstrlen(str);
03303     QTextCodec *codec = QTextCodec::codecForLocale();
03304     if (codec)
03305         return codec->toUnicode(str, size);
03306 #endif // !QT_NO_TEXTCODEC
03307     return fromLatin1(str, size);
03308 }
03309 
03323 QString QString::fromAscii(const char *str, int size)
03324 {
03325     return QString(fromAscii_helper(str, size), 0);
03326 }
03327 
03328 static ushort *addOne(ushort *qch, QString &str)
03329 {
03330     long sidx = qch - str.utf16();
03331     str.resize(str.length()+1);
03332     return (ushort *)str.data() + sidx;
03333 }
03334 
03344 QString QString::fromUtf8(const char *str, int size)
03345 {
03346     if (!str)
03347         return QString();
03348     if (size < 0)
03349         size = qstrlen(str);
03350 
03351     QString result;
03352     result.resize(size); // worst case
03353     ushort *qch = result.d->data;
03354     uint uc = 0;
03355     int need = 0;
03356     int error = -1;
03357     uchar ch;
03358     for (int i = 0; i < size; ++i) {
03359         ch = str[i];
03360         if (need) {
03361             if ((ch&0xc0) == 0x80) {
03362                 uc = (uc << 6) | (ch & 0x3f);
03363                 need--;
03364                 if (!need) {
03365                     if (uc > 0xffff) {
03366                         // surrogate pair
03367                         uc -= 0x10000;
03368                         ushort high = uc/0x400 + 0xd800;
03369                         ushort low = uc%0x400 + 0xdc00;
03370                         *qch++ = high;
03371                         *qch++ = low;
03372                     } else {
03373                         *qch++ = uc;
03374                     }
03375                 }
03376             } else {
03377                 // See QString::toUtf8() for explanation.
03378                 //
03379                 // The surrogate below corresponds to a Unicode value of (0x10fe00+ch) which
03380                 // is in one of the private use areas of Unicode.
03381                 i = error;
03382                 qch = addOne(qch, result);
03383                 *qch++ = 0xdbff;
03384                 *qch++ = 0xde00 + ((uchar)str[i]);
03385                 need = 0;
03386             }
03387         } else {
03388             if (ch < 128) {
03389                 *qch++ = ch;
03390             } else if ((ch & 0xe0) == 0xc0) {
03391                 uc = ch & 0x1f;
03392                 need = 1;
03393                 error = i;
03394             } else if ((ch & 0xf0) == 0xe0) {
03395                 uc = ch & 0x0f;
03396                 need = 2;
03397                 error = i;
03398             } else if ((ch&0xf8) == 0xf0) {
03399                 uc = ch & 0x07;
03400                 need = 3;
03401                 error = i;
03402             } else {
03403                 // Error
03404                 qch = addOne(qch, result);
03405                 *qch++ = 0xdbff;
03406                 *qch++ = 0xde00 + ((uchar)str[i]);
03407             }
03408         }
03409     }
03410     if (need) {
03411         // we have some invalid characters remaining we need to add to the string
03412         for (int i = error; i < size; ++i) {
03413             qch = addOne(qch, result);
03414             *qch++ = 0xdbff;
03415             *qch++ = 0xde00 + (uchar)str[i];
03416         }
03417     }
03418 
03419     result.truncate(qch - result.d->data);
03420     return result;
03421 }
03422 
03434 QString QString::fromUtf16(const ushort *unicode, int size)
03435 {
03436     if (!unicode)
03437         return QString();
03438     if (size < 0) {
03439         size = 0;
03440         while (unicode[size] != 0)
03441             ++size;
03442     }
03443     return QString((const QChar *)unicode, size);
03444 }
03445 
03446 
03458 QString QString::fromUcs4(const uint *unicode, int size)
03459 {
03460     if (!unicode)
03461         return QString();
03462     if (size < 0) {
03463         size = 0;
03464         while (unicode[size] != 0)
03465             ++size;
03466     }
03467 
03468     QString s;
03469     s.resize(size*2); // worst case
03470     QChar *uc = s.data();
03471     for (int i = 0; i < size; ++i) {
03472         uint u = unicode[i];
03473         if (u > 0xffff) {
03474             // decompose into a surrogate pair
03475             u -= 0x10000;
03476             *uc = QChar(u/0x400 + 0xd800);
03477             ++uc;
03478             u = u%0x400 + 0xdc00;
03479         }
03480         *uc = QChar(u);
03481         ++uc;
03482     }
03483     s.resize(uc - s.data());
03484     return s;
03485 }
03486 
03496 QString& QString::setUnicode(const QChar *unicode, int size)
03497 {
03498      resize(size);
03499      if (unicode && size)
03500          memcpy(d->data, unicode, size * sizeof(QChar));
03501      return *this;
03502 }
03503 
03534 QString QString::simplified() const
03535 {
03536     if (d->size == 0)
03537         return *this;
03538     QString result;
03539     result.resize(d->size);
03540     const QChar *from = (const QChar*) d->data;
03541     const QChar *fromend = (const QChar*) from+d->size;
03542     int outc=0;
03543     QChar *to   = (QChar*) result.d->data;
03544     for (;;) {
03545         while (from!=fromend && from->isSpace())
03546             from++;
03547         while (from!=fromend && !from->isSpace())
03548             to[outc++] = *from++;
03549         if (from!=fromend)
03550             to[outc++] = QLatin1Char(' ');
03551         else
03552             break;
03553     }
03554     if (outc > 0 && to[outc-1] == QLatin1Char(' '))
03555         outc--;
03556     result.truncate(outc);
03557     return result;
03558 }
03559 
03579 QString QString::trimmed() const
03580 {
03581     if (d->size == 0)
03582         return *this;
03583     const QChar *s = (const QChar*)d->data;
03584     if (!s->isSpace() && !s[d->size-1].isSpace())
03585         return *this;
03586     int start = 0;
03587     int end = d->size - 1;
03588     while (start<=end && s[start].isSpace())  // skip white space from start
03589         start++;
03590     if (start <= end) {                          // only white space
03591         while (end && s[end].isSpace())           // skip white space from end
03592             end--;
03593     }
03594     int l = end - start + 1;
03595     if (l <= 0) {
03596         shared_empty.ref.ref();
03597         return QString(&shared_empty, 0);
03598     }
03599     return QString(s + start, l);
03600 }
03601 
03669 void QString::truncate(int pos)
03670 {
03671     if (pos < d->size)
03672         resize(pos);
03673 }
03674 
03675 
03692 void QString::chop(int n)
03693 {
03694     if (n > 0)
03695         resize(d->size - n);
03696 }
03697 
03713 QString& QString::fill(QChar ch, int size)
03714 {
03715     resize(size < 0 ? d->size : size);
03716     if (d->size) {
03717         QChar *i = (QChar*)d->data + d->size;
03718         QChar *b = (QChar*)d->data;
03719         while (i != b)
03720            *--i = ch;
03721     }
03722     return *this;
03723 }
03724 
04081 int QString::compare(const QString &other) const
04082 {
04083     return ucstrcmp(*this, other);
04084 }
04085 
04092 int QString::compare(const QString &other, Qt::CaseSensitivity cs) const
04093 {
04094     return (cs == Qt::CaseSensitive) ? ucstrcmp(*this, other) : ucstricmp(*this, other);
04095 }
04096 
04103 int QString::compare(const QLatin1String &other, Qt::CaseSensitivity cs) const
04104 {
04105     const ushort *uc = d->data;
04106     const ushort *e = uc + d->size;
04107     const uchar *c = (uchar *)other.latin1();
04108 
04109     if (!c)
04110         return d->size;
04111 
04112     if (cs == Qt::CaseSensitive) {
04113         while (uc != e && *c && *uc == *c)
04114             uc++, c++;
04115 
04116         return *uc - *c;
04117     } else {
04118         while (uc != e && *c && QUnicodeTables::lower(*uc) == QUnicodeTables::lower(*c))
04119             uc++, c++;
04120 
04121         return QUnicodeTables::lower(*uc) - QUnicodeTables::lower(*c);
04122     }
04123 }
04124 
04149 #if !defined(CSTR_LESS_THAN)
04150 #define CSTR_LESS_THAN    1
04151 #define CSTR_EQUAL        2
04152 #define CSTR_GREATER_THAN 3
04153 #endif
04154 
04155 int QString::localeAwareCompare(const QString &other) const
04156 {
04157     // do the right thing for null and empty
04158     if (isEmpty() || other.isEmpty())
04159         return compare(other);
04160 
04161 #if defined(Q_OS_WIN32)
04162     int res;
04163     QT_WA({
04164         const TCHAR* s1 = (TCHAR*)utf16();
04165         const TCHAR* s2 = (TCHAR*)other.utf16();
04166         res = CompareStringW(GetThreadLocale(), 0, s1, length(), s2, other.length());
04167     } , {
04168         QByteArray s1 = toLocal8Bit();
04169         QByteArray s2 = other.toLocal8Bit();
04170         res = CompareStringA(GetThreadLocale(), 0, s1.data(), s1.length(), s2.data(), s2.length());
04171     });
04172 
04173     switch (res) {
04174     case CSTR_LESS_THAN:
04175         return -1;
04176     case CSTR_GREATER_THAN:
04177         return 1;
04178     default:
04179         return 0;
04180     }
04181 #elif defined(Q_OS_UNIX)
04182     // declared in <string.h>
04183     int delta = strcoll(toLocal8Bit(), other.toLocal8Bit());
04184     if (delta == 0)
04185         delta = ucstrcmp(*this, other);
04186     return delta;
04187 #else
04188     return ucstrcmp(*this, other);
04189 #endif
04190 }
04191 
04192 
04211 const ushort *QString::utf16() const
04212 {
04213     if (d->data != d->array) {
04214         QString *that = const_cast<QString*>(this);
04215         that->realloc();   // ensure '\\0'-termination for ::fromRawData strings
04216         return that->d->data;
04217     }
04218     return d->array;
04219 }
04220 
04245 QString QString::leftJustified(int width, QChar fill, bool truncate) const
04246 {
04247     QString result;
04248     int len = length();
04249     int padlen = width - len;
04250     if (padlen > 0) {
04251         result.resize(len+padlen);
04252         if (len)
04253             memcpy(result.d->data, d->data, sizeof(QChar)*len);
04254         QChar *uc = (QChar*)result.d->data + len;
04255         while (padlen--)
04256            * uc++ = fill;
04257     } else {
04258         if (truncate)
04259             result = left(width);
04260         else
04261             result = *this;
04262     }
04263     return result;
04264 }
04265 
04290 QString QString::rightJustified(int width, QChar fill, bool truncate) const
04291 {
04292     QString result;
04293     int len = length();
04294     int padlen = width - len;
04295     if (padlen > 0) {
04296         result.resize(len+padlen);
04297         QChar *uc = (QChar*)result.d->data;
04298         while (padlen--)
04299            * uc++ = fill;
04300         if (len)
04301             memcpy(uc, d->data, sizeof(QChar)*len);
04302     } else {
04303         if (truncate)
04304             result = left(width);
04305         else
04306             result = *this;
04307     }
04308     return result;
04309 }
04310 
04322 QString QString::toLower() const
04323 {
04324     int l = d->size;
04325     if (l) {
04326         QChar *p = (QChar*)d->data;
04327         if (p) {
04328             while (l) {
04329                 bool different;
04330                 if (p->unicode() & 0xFF80)
04331                     different = (*p != QUnicodeTables::lower(*p));
04332                 else
04333                     different = ((uint)p->cell() - 'A' < 26);
04334 
04335                 if (different) {
04336                     QString s(*this);
04337                     p = (QChar*)s.data() + (p - (QChar*)d->data);
04338                     while (l) {
04339                         *p = QUnicodeTables::lower(*p);
04340                         l--;
04341                         p++;
04342                     }
04343                     return s;
04344                 }
04345                 l--;
04346                 p++;
04347             }
04348         }
04349     }
04350     return *this;
04351 }
04352 
04364 QString QString::toUpper() const
04365 {
04366     int l = d->size;
04367     if (l) {
04368         QChar *p = (QChar*)d->data;
04369         if (p) {
04370             while (l) {
04371                 bool different;
04372                 if (p->unicode() & 0xFF80)
04373                     different = (*p != QUnicodeTables::upper(*p));
04374                 else
04375                     different = ((uint)p->cell() - 'a' < 26);
04376 
04377                 if (different) {
04378                     QString s(*this);
04379                     p = s.data() + (p - (QChar*)d->data);
04380                     while (l) {
04381                         *p = QUnicodeTables::upper(*p);
04382                         l--;
04383                         p++;
04384                     }
04385                     return s;
04386                 }
04387                 l--;
04388                 p++;
04389             }
04390         }
04391     }
04392     return *this;
04393 }
04394 
04395 
04434 QString &QString::sprintf(const char *cformat, ...)
04435 {
04436     va_list ap;
04437     va_start(ap, cformat);
04438     QString &s = vsprintf(cformat, ap);
04439     va_end(ap);
04440     return s;
04441 }
04442 
04454 QString &QString::vsprintf(const char* cformat, va_list ap)
04455 {
04456     QLocale locale(QLocale::C);
04457 
04458     if (!cformat || !*cformat) {
04459         // Qt 1.x compat
04460         *this = fromLatin1("");
04461         return *this;
04462     }
04463 
04464     // Parse cformat
04465 
04466     QString result;
04467     const char *c = cformat;
04468     for (;;) {
04469         // Copy non-escape chars to result
04470         while (*c != '\0' && *c != '%')
04471             result.append(QLatin1Char(*c++));
04472 
04473         if (*c == '\0')
04474             break;
04475 
04476         // Found '%'
04477         const char *escape_start = c;
04478         ++c;
04479 
04480         if (*c == '\0') {
04481             result.append(QLatin1Char('%')); // a % at the end of the string - treat as non-escape text
04482             break;
04483         }
04484         if (*c == '%') {
04485             result.append(QLatin1Char('%')); // %%
04486             ++c;
04487             continue;
04488         }
04489 
04490         // Parse flag characters
04491         uint flags = 0;
04492         bool no_more_flags = false;
04493         do {
04494             switch (*c) {
04495                 case '#': flags |= QLocalePrivate::Alternate; break;
04496                 case '0': flags |= QLocalePrivate::ZeroPadded; break;
04497                 case '-': flags |= QLocalePrivate::LeftAdjusted; break;
04498                 case ' ': flags |= QLocalePrivate::BlankBeforePositive; break;
04499                 case '+': flags |= QLocalePrivate::AlwaysShowSign; break;
04500                 case '\'': flags |= QLocalePrivate::ThousandsGroup; break;
04501                 default: no_more_flags = true; break;
04502             }
04503 
04504             if (!no_more_flags)
04505                 ++c;
04506         } while (!no_more_flags);
04507 
04508         if (*c == '\0') {
04509             result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
04510             break;
04511         }
04512 
04513         // Parse field width
04514         int width = -1; // -1 means unspecified
04515         if (qIsDigit(*c)) {
04516             QString width_str;
04517             while (*c != '\0' && qIsDigit(*c))
04518                 width_str.append(QLatin1Char(*c++));
04519 
04520             // can't be negative - started with a digit
04521             // contains at least one digit
04522             width = width_str.toInt();
04523         }
04524         else if (*c == '*') {
04525             width = va_arg(ap, int);
04526             if (width < 0)
04527                 width = -1; // treat all negative numbers as unspecified
04528             ++c;
04529         }
04530 
04531         if (*c == '\0') {
04532             result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
04533             break;
04534         }
04535 
04536         // Parse precision
04537         int precision = -1; // -1 means unspecified
04538         if (*c == '.') {
04539             ++c;
04540             if (qIsDigit(*c)) {
04541                 QString precision_str;
04542                 while (*c != '\0' && qIsDigit(*c))
04543                     precision_str.append(QLatin1Char(*c++));
04544 
04545                 // can't be negative - started with a digit
04546                 // contains at least one digit
04547                 precision = precision_str.toInt();
04548             }
04549             else if (*c == '*') {
04550                 precision = va_arg(ap, int);
04551                 if (precision < 0)
04552                     precision = -1; // treat all negative numbers as unspecified
04553                 ++c;
04554             }
04555         }
04556 
04557         if (*c == '\0') {
04558             result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
04559             break;
04560         }
04561 
04562         // Parse the length modifier
04563         enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t };
04564         LengthMod length_mod = lm_none;
04565         switch (*c) {
04566             case 'h':
04567                 ++c;
04568                 if (*c == 'h') {
04569                     length_mod = lm_hh;
04570                     ++c;
04571                 }
04572                 else
04573                     length_mod = lm_h;
04574                 break;
04575 
04576             case 'l':
04577                 ++c;
04578                 if (*c == 'l') {
04579                     length_mod = lm_ll;
04580                     ++c;
04581                 }
04582                 else
04583                     length_mod = lm_l;
04584                 break;
04585 
04586             case 'L':
04587                 ++c;
04588                 length_mod = lm_L;
04589                 break;
04590 
04591             case 'j':
04592                 ++c;
04593                 length_mod = lm_j;
04594                 break;
04595 
04596             case 'z':
04597             case 'Z':
04598                 ++c;
04599                 length_mod = lm_z;
04600                 break;
04601 
04602             case 't':
04603                 ++c;
04604                 length_mod = lm_t;
04605                 break;
04606 
04607             default: break;
04608         }
04609 
04610         if (*c == '\0') {
04611             result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text
04612             break;
04613         }
04614 
04615         // Parse the conversion specifier and do the conversion
04616         QString subst;
04617         switch (*c) {
04618             case 'd':
04619             case 'i': {
04620                 qint64 i;
04621                 switch (length_mod) {
04622                     case lm_none: i = va_arg(ap, int); break;
04623                     case lm_hh: i = va_arg(ap, int); break;
04624                     case lm_h: i = va_arg(ap, int); break;
04625                     case lm_l: i = va_arg(ap, long int); break;
04626                     case lm_ll: i = va_arg(ap, qint64); break;
04627                     case lm_j: i = va_arg(ap, long int); break;
04628                     case lm_z: i = va_arg(ap, size_t); break;
04629                     case lm_t: i = va_arg(ap, int); break;
04630                     default: i = 0; break;
04631                 }
04632                 subst = locale.d()->longLongToString(i, precision, 10, width, flags);
04633                 ++c;
04634                 break;
04635             }
04636             case 'o':
04637             case 'u':
04638             case 'x':
04639             case 'X': {
04640                 quint64 u;
04641                 switch (length_mod) {
04642                     case lm_none: u = va_arg(ap, uint); break;
04643                     case lm_hh: u = va_arg(ap, uint); break;
04644                     case lm_h: u = va_arg(ap, uint); break;
04645                     case lm_l: u = va_arg(ap, ulong); break;
04646                     case lm_ll: u = va_arg(ap, quint64); break;
04647                     default: u = 0; break;
04648                 }
04649 
04650                 if (qIsUpper(*c))
04651                     flags |= QLocalePrivate::CapitalEorX;
04652 
04653                 int base = 10;
04654                 switch (qToLower(*c)) {
04655                     case 'o':
04656                         base = 8; break;
04657                     case 'u':
04658                         base = 10; break;
04659                     case 'x':
04660                         base = 16; break;
04661                     default: break;
04662                 }
04663                 subst = locale.d()->unsLongLongToString(u, precision, base, width, flags);
04664                 ++c;
04665                 break;
04666             }
04667             case 'E':
04668             case 'e':
04669             case 'F':
04670             case 'f':
04671             case 'G':
04672             case 'g':
04673             case 'A':
04674             case 'a': {
04675                 double d;
04676                 if (length_mod == lm_L)
04677                     d = va_arg(ap, long double); // not supported - converted to a double
04678                 else
04679                     d = va_arg(ap, double);
04680 
04681                 if (qIsUpper(*c))
04682                     flags |= QLocalePrivate::CapitalEorX;
04683 
04684                 QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
04685                 switch (qToLower(*c)) {
04686                     case 'e': form = QLocalePrivate::DFExponent; break;
04687                     case 'a':                             // not supported - decimal form used instead
04688                     case 'f': form = QLocalePrivate::DFDecimal; break;
04689                     case 'g': form = QLocalePrivate::DFSignificantDigits; break;
04690                     default: break;
04691                 }
04692                 subst = locale.d()->doubleToString(d, precision, form, width, flags);
04693                 ++c;
04694                 break;
04695             }
04696             case 'c': {
04697                 if (length_mod == lm_l)
04698                     subst = QChar((ushort) va_arg(ap, int));
04699                 else
04700                     subst = QLatin1Char((uchar) va_arg(ap, int));
04701                 ++c;
04702                 break;
04703             }
04704             case 's': {
04705                 if (length_mod == lm_l) {
04706                     const ushort *buff = va_arg(ap, const ushort*);
04707                     const ushort *ch = buff;
04708                     while (*ch != 0)
04709                         ++ch;
04710                     subst.setUtf16(buff, ch - buff);
04711                 } else
04712                     subst = QString::fromUtf8(va_arg(ap, const char*));
04713                 if (precision != -1)
04714                     subst.truncate(precision);
04715                 ++c;
04716                 break;
04717             }
04718             case 'p': {
04719                 void *arg = va_arg(ap, void*);
04720 #ifdef Q_OS_WIN64
04721                 quint64 i = reinterpret_cast<quint64>(arg);
04722 #else
04723                 quint64 i = reinterpret_cast<unsigned long>(arg);
04724 #endif
04725                 flags |= QLocalePrivate::Alternate;
04726                 subst = locale.d()->unsLongLongToString(i, precision, 16, width, flags);
04727                 ++c;
04728                 break;
04729             }
04730             case 'n':
04731                 switch (length_mod) {
04732                     case lm_hh: {
04733                         signed char *n = va_arg(ap, signed char*);
04734                         *n = result.length();
04735                         break;
04736                     }
04737                     case lm_h: {
04738                         short int *n = va_arg(ap, short int*);
04739                         *n = result.length();
04740                             break;
04741                     }
04742                     case lm_l: {
04743                         long int *n = va_arg(ap, long int*);
04744                         *n = result.length();
04745                         break;
04746                     }
04747                     case lm_ll: {
04748                         qint64 *n = va_arg(ap, qint64*);
04749                         volatile uint tmp = result.length(); // egcs-2.91.66 gets internal
04750                         *n = tmp;                             // compiler error without volatile
04751                         break;
04752                     }
04753                     default: {
04754                         int *n = va_arg(ap, int*);
04755                         *n = result.length();
04756                         break;
04757                     }
04758                 }
04759                 ++c;
04760                 break;
04761 
04762             default: // bad escape, treat as non-escape text
04763                 for (const char *cc = escape_start; cc != c; ++cc)
04764                     result.append(QLatin1Char(*cc));
04765                 continue;
04766         }
04767 
04768         if (flags & QLocalePrivate::LeftAdjusted)
04769             result.append(subst.leftJustified(width));
04770         else
04771             result.append(subst.rightJustified(width));
04772     }
04773 
04774     *this = result;
04775 
04776     return *this;
04777 }
04778 
04801 qint64 QString::toLongLong(bool *ok, int base) const
04802 {
04803 #if defined(QT_CHECK_RANGE)
04804     if (base != 0 && (base < 2 || base > 36)) {
04805         qWarning("QString::toLongLong: Invalid base (%d)", base);
04806         base = 10;
04807     }
04808 #endif
04809 
04810     bool my_ok;
04811     QLocale def_locale;
04812     qint64 result = def_locale.d()->stringToLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators);
04813     if (my_ok) {
04814         if (ok != 0)
04815             *ok = true;
04816         return result;
04817     }
04818 
04819     QLocale c_locale(QLocale::C);
04820     return c_locale.d()->stringToLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators);
04821 }
04822 
04845 quint64 QString::toULongLong(bool *ok, int base) const
04846 {
04847 #if defined(QT_CHECK_RANGE)
04848     if (base != 0 && (base < 2 || base > 36)) {
04849         qWarning("QString::toULongLong: Invalid base (%d)", base);
04850         base = 10;
04851     }
04852 #endif
04853 
04854     bool my_ok;
04855     QLocale def_locale;
04856     quint64 result = def_locale.d()->stringToUnsLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators);
04857     if (my_ok) {
04858         if (ok != 0)
04859             *ok = true;
04860         return result;
04861     }
04862 
04863     QLocale c_locale(QLocale::C);
04864     return c_locale.d()->stringToUnsLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators);
04865 }
04866 
04891 long QString::toLong(bool *ok, int base) const
04892 {
04893     qint64 v = toLongLong(ok, base);
04894     if (v < LONG_MIN || v > LONG_MAX) {
04895         if (ok)
04896             *ok = false;
04897         v = 0;
04898     }
04899     return (long)v;
04900 }
04901 
04926 ulong QString::toULong(bool *ok, int base) const
04927 {
04928     quint64 v = toULongLong(ok, base);
04929     if (v > ULONG_MAX) {
04930         if (ok)
04931             *ok = false;
04932         v = 0;
04933     }
04934     return (ulong)v;
04935 }
04936 
04937 
04960 int QString::toInt(bool *ok, int base) const
04961 {
04962     qint64 v = toLongLong(ok, base);
04963     if (v < INT_MIN || v > INT_MAX) {
04964         if (ok)
04965             *ok = false;
04966         v = 0;
04967     }
04968     return v;
04969 }
04970 
04993 uint QString::toUInt(bool *ok, int base) const
04994 {
04995     quint64 v = toULongLong(ok, base);
04996     if (v > UINT_MAX) {
04997         if (ok)
04998             *ok = false;
04999         v = 0;
05000     }
05001     return (uint)v;
05002 }
05003 
05026 short QString::toShort(bool *ok, int base) const
05027 {
05028     long v = toLongLong(ok, base);
05029     if (v < SHRT_MIN || v > SHRT_MAX) {
05030         if (ok)
05031             *ok = false;
05032         v = 0;
05033     }
05034     return (short)v;
05035 }
05036 
05059 ushort QString::toUShort(bool *ok, int base) const
05060 {
05061     ulong v = toULongLong(ok, base);
05062     if (v > USHRT_MAX) {
05063         if (ok)
05064             *ok = false;
05065         v = 0;
05066     }
05067     return (ushort)v;
05068 }
05069 
05070 
05122 double QString::toDouble(bool *ok) const
05123 {
05124     bool my_ok;
05125     QLocale def_locale;
05126     double result = def_locale.d()->stringToDouble(*this, &my_ok, QLocalePrivate::FailOnGroupSeparators);
05127     if (my_ok) {
05128         if (ok != 0)
05129             *ok = true;
05130         return result;
05131     }
05132 
05133     QLocale c_locale(QLocale::C);
05134     return c_locale.d()->stringToDouble(*this, ok, QLocalePrivate::FailOnGroupSeparators);
05135 }
05136 
05153 #define QT_MAX_FLOAT 3.4028234663852886e+38
05154 
05155 float QString::toFloat(bool *ok) const
05156 {
05157     bool myOk;
05158     double d = toDouble(&myOk);
05159     if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) {
05160         if (ok != 0)
05161             *ok = false;
05162         return 0.0;
05163     }
05164     if (ok != 0)
05165         *ok = true;
05166     return (float) d;
05167 }
05168 
05201 QString &QString::setNum(qlonglong n, int base)
05202 {
05203 #if defined(QT_CHECK_RANGE)
05204     if (base < 2 || base > 36) {
05205         qWarning("QString::setNum: Invalid base (%d)", base);
05206         base = 10;
05207     }
05208 #endif
05209     QLocale locale(QLocale::C);
05210     *this = locale.d()->longLongToString(n, -1, base);
05211     return *this;
05212 }
05213 
05217 QString &QString::setNum(qulonglong n, int base)
05218 {
05219 #if defined(QT_CHECK_RANGE)
05220     if (base < 2 || base > 36) {
05221         qWarning("QString::setNum: Invalid base (%d)", base);
05222         base = 10;
05223     }
05224 #endif
05225     QLocale locale(QLocale::C);
05226     *this = locale.d()->unsLongLongToString(n, -1, base);
05227     return *this;
05228 }
05229 
05255 QString &QString::setNum(double n, char f, int prec)
05256 {
05257     QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
05258     uint flags = 0;
05259 
05260     if (qIsUpper(f))
05261         flags = QLocalePrivate::CapitalEorX;
05262     f = qToLower(f);
05263 
05264     switch (f) {
05265         case 'f':
05266             form = QLocalePrivate::DFDecimal;
05267             break;
05268         case 'e':
05269             form = QLocalePrivate::DFExponent;
05270             break;
05271         case 'g':
05272             form = QLocalePrivate::DFSignificantDigits;
05273             break;
05274         default:
05275 #if defined(QT_CHECK_RANGE)
05276             qWarning("QString::setNum: Invalid format char '%c'", f);
05277 #endif
05278             break;
05279     }
05280 
05281     QLocale locale(QLocale::C);
05282     *this = locale.d()->doubleToString(n, prec, form, -1, flags);
05283     return *this;
05284 }
05285 
05314 QString QString::number(long n, int base)
05315 {
05316     QString s;
05317     s.setNum(n, base);
05318     return s;
05319 }
05320 
05326 QString QString::number(ulong n, int base)
05327 {
05328     QString s;
05329     s.setNum(n, base);
05330     return s;
05331 }
05332 
05336 QString QString::number(int n, int base)
05337 {
05338     QString s;
05339     s.setNum(n, base);
05340     return s;
05341 }
05342 
05346 QString QString::number(uint n, int base)
05347 {
05348     QString s;
05349     s.setNum(n, base);
05350     return s;
05351 }
05352 
05356 QString QString::number(qlonglong n, int base)
05357 {
05358     QString s;
05359     s.setNum(n, base);
05360     return s;
05361 }
05362 
05366 QString QString::number(qulonglong n, int base)
05367 {
05368     QString s;
05369     s.setNum(n, base);
05370     return s;
05371 }
05372 
05373 
05388 QString QString::number(double n, char f, int prec)
05389 {
05390     QString s;
05391     s.setNum(n, f, prec);
05392     return s;
05393 }
05394 
05416 QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
05417 {
05418     QStringList list;
05419     int start = 0;
05420     int extra = 0;
05421     int end;
05422     while ((end = indexOf(sep, start + extra, cs)) != -1) {
05423         if (start != end || behavior == KeepEmptyParts)
05424             list.append(mid(start, end - start));
05425         start = end + sep.size();
05426         extra = (sep.size() == 0 ? 1 : 0);
05427     }
05428     if (start != size() || behavior == KeepEmptyParts)
05429         list.append(mid(start));
05430     return list;
05431 }
05432 
05436 QStringList QString::split(const QChar &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
05437 {
05438     QStringList list;
05439     int start = 0;
05440     int end;
05441     while ((end = indexOf(sep, start, cs)) != -1) {
05442         if (start != end || behavior == KeepEmptyParts)
05443             list.append(mid(start, end - start));
05444         start = end + 1;
05445     }
05446     if (start != size() || behavior == KeepEmptyParts)
05447         list.append(mid(start));
05448     return list;
05449 }
05450 
05451 #ifndef QT_NO_REGEXP
05452 
05487 QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
05488 {
05489     QStringList list;
05490     int start = 0;
05491     int extra = 0;
05492     int end;
05493     while ((end = indexOf(rx, start + extra)) != -1) {
05494         int matchedLen = rx.matchedLength();
05495         if (start != end || behavior == KeepEmptyParts)
05496             list.append(mid(start, end - start));
05497         start = end + matchedLen;
05498         extra = (matchedLen == 0) ? 1 : 0;
05499     }
05500     if (start != size() || behavior == KeepEmptyParts)
05501         list.append(mid(start));
05502     return list;
05503 }
05504 #endif
05505 
05523 QString QString::normalized(NormalizationForm form) const
05524 {
05525     return QUnicodeTables::normalize(*this, form);
05526 }
05527 
05534 QString QString::normalized(NormalizationForm form, QChar::UnicodeVersion version) const
05535 {
05536     return QUnicodeTables::normalize(*this, form, version);
05537 }
05538 
05539 struct ArgEscapeData
05540 {
05541     int min_escape;            // lowest escape sequence number
05542     int occurrences;           // number of occurrences of the lowest escape sequence number
05543     int locale_occurrences;    // number of occurrences of the lowest escape sequence number that
05544                                // contain 'L'
05545     int escape_len;            // total length of escape sequences which will be replaced
05546 };
05547 
05548 static ArgEscapeData findArgEscapes(const QString &s)
05549 {
05550     const QChar *uc_begin = s.unicode();
05551     const QChar *uc_end = uc_begin + s.length();
05552 
05553     ArgEscapeData d;
05554 
05555     d.min_escape = INT_MAX;
05556     d.occurrences = 0;
05557     d.escape_len = 0;
05558     d.locale_occurrences = 0;
05559 
05560     const QChar *c = uc_begin;
05561     while (c != uc_end) {
05562         while (c != uc_end && c->unicode() != '%')
05563             ++c;
05564 
05565         if (c == uc_end)
05566             break;
05567         const QChar *escape_start = c;
05568         if (++c == uc_end)
05569             break;
05570 
05571         bool locale_arg = false;
05572         if (c->unicode() == 'L') {
05573             locale_arg = true;
05574             if (++c == uc_end)
05575                 break;
05576         }
05577 
05578         if (c->digitValue() == -1)
05579             continue;
05580 
05581         int escape = c->digitValue();
05582         ++c;
05583 
05584         if (c != uc_end && c->digitValue() != -1) {
05585             escape = (10 * escape) + c->digitValue();
05586             ++c;
05587         }
05588 
05589         if (escape > d.min_escape)
05590             continue;
05591 
05592         if (escape < d.min_escape) {
05593             d.min_escape = escape;
05594             d.occurrences = 0;
05595             d.escape_len = 0;
05596             d.locale_occurrences = 0;
05597         }
05598 
05599         ++d.occurrences;
05600         if (locale_arg)
05601             ++d.locale_occurrences;
05602         d.escape_len += c - escape_start;
05603     }
05604     return d;
05605 }
05606 
05607 static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int field_width,
05608                                  const QString &arg, const QString &larg, const QChar &fillChar = QLatin1Char(' '))
05609 {
05610     const QChar *uc_begin = s.unicode();
05611     const QChar *uc_end = uc_begin + s.length();
05612 
05613     int abs_field_width = qAbs(field_width);
05614     int result_len = s.length()
05615                      - d.escape_len
05616                      + (d.occurrences - d.locale_occurrences)
05617                      *qMax(abs_field_width, arg.length())
05618                      + d.locale_occurrences
05619                      *qMax(abs_field_width, larg.length());
05620 
05621     QString result;
05622     result.resize(result_len);
05623     QChar *result_buff = (QChar*) result.unicode();
05624 
05625     QChar *rc = result_buff;
05626     const QChar *c = uc_begin;
05627     int repl_cnt = 0;
05628     while (c != uc_end) {
05629         /* We don't have to check if we run off the end of the string with c,
05630            because as long as d.occurrences > 0 we KNOW there are valid escape
05631            sequences. */
05632 
05633         const QChar *text_start = c;
05634 
05635         while (c->unicode() != '%')
05636             ++c;
05637 
05638         const QChar *escape_start = c++;
05639 
05640         bool locale_arg = false;
05641         if (c->unicode() == 'L') {
05642             locale_arg = true;
05643             ++c;
05644         }
05645 
05646         int escape = c->digitValue();
05647         if (escape != -1) {
05648             if (c + 1 != uc_end && (c + 1)->digitValue() != -1) {
05649                 escape = (10 * escape) + (c + 1)->digitValue();
05650                 ++c;
05651             }
05652         }
05653 
05654         if (escape != d.min_escape) {
05655             memcpy(rc, text_start, (c - text_start)*sizeof(QChar));
05656             rc += c - text_start;
05657         }
05658         else {
05659             ++c;
05660 
05661             memcpy(rc, text_start, (escape_start - text_start)*sizeof(QChar));
05662             rc += escape_start - text_start;
05663 
05664             uint pad_chars;
05665             if (locale_arg)
05666                 pad_chars = qMax(abs_field_width, larg.length()) - larg.length();
05667             else
05668                 pad_chars = qMax(abs_field_width, arg.length()) - arg.length();
05669 
05670             if (field_width > 0) { // left padded
05671                 for (uint i = 0; i < pad_chars; ++i)
05672                     (rc++)->unicode() = fillChar.unicode();
05673             }
05674 
05675             if (locale_arg) {
05676                 memcpy(rc, larg.unicode(), larg.length()*sizeof(QChar));
05677                 rc += larg.length();
05678             }
05679             else {
05680                 memcpy(rc, arg.unicode(), arg.length()*sizeof(QChar));
05681                 rc += arg.length();
05682             }
05683 
05684             if (field_width < 0) { // right padded
05685                 for (uint i = 0; i < pad_chars; ++i)
05686                     (rc++)->unicode() = fillChar.unicode();
05687             }
05688 
05689             if (++repl_cnt == d.occurrences) {
05690                 memcpy(rc, c, (uc_end - c)*sizeof(QChar));
05691                 rc += uc_end - c;
05692                 Q_ASSERT(rc - result_buff == result_len);
05693                 c = uc_end;
05694             }
05695         }
05696     }
05697     Q_ASSERT(rc == result_buff + result_len);
05698 
05699     return result;
05700 }
05701 
05727 QString QString::arg(const QString &a, int fieldWidth, const QChar &fillChar) const
05728 {
05729     ArgEscapeData d = findArgEscapes(*this);
05730 
05731     if (d.occurrences == 0) {
05732         qWarning("QString::arg: Argument missing: %s, %s", toLocal8Bit().data(),
05733                   a.toLocal8Bit().data());
05734         return *this;
05735     }
05736     return replaceArgEscapes(*this, d, fieldWidth, a, a, fillChar);
05737 }
05738 
05850 QString QString::arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
05851 {
05852     ArgEscapeData d = findArgEscapes(*this);
05853 
05854     if (d.occurrences == 0) {
05855         qWarning("QString::arg: Argument missing: %s, %lld", toLocal8Bit().data(), a);
05856         return *this;
05857     }
05858 
05859     QString arg;
05860     if (d.occurrences > d.locale_occurrences)
05861         arg = number(a, base);
05862 
05863     QString locale_arg;
05864     if (d.locale_occurrences > 0) {
05865         QLocale locale;
05866         locale_arg = locale.d()->longLongToString(a, -1, base, -1, QLocalePrivate::ThousandsGroup);
05867     }
05868 
05869     return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
05870 }
05871 
05879 QString QString::arg(qulonglong a, int fieldWidth, int base, const QChar &fillChar) const
05880 {
05881     ArgEscapeData d = findArgEscapes(*this);
05882 
05883     if (d.occurrences == 0) {
05884         qWarning("QString::arg: Argument missing: %s, %llu", toLocal8Bit().data(), a);
05885         return *this;
05886     }
05887 
05888     QString arg;
05889     if (d.occurrences > d.locale_occurrences)
05890         arg = number(a, base);
05891 
05892     QString locale_arg;
05893     if (d.locale_occurrences > 0) {
05894         QLocale locale;
05895         locale_arg = locale.d()->unsLongLongToString(a, -1, base, -1, QLocalePrivate::ThousandsGroup);
05896     }
05897 
05898     return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
05899 }
05900 
05924 QString QString::arg(QChar a, int fieldWidth, const QChar &fillChar) const
05925 {
05926     QString c;
05927     c += a;
05928     return arg(c, fieldWidth, fillChar);
05929 }
05930 
05936 QString QString::arg(char a, int fieldWidth, const QChar &fillChar) const
05937 {
05938     QString c;
05939     c += QLatin1Char(a);
05940     return arg(c, fieldWidth, fillChar);
05941 }
05942 
05978 QString QString::arg(double a, int fieldWidth, char fmt, int prec, const QChar &fillChar) const
05979 {
05980     ArgEscapeData d = findArgEscapes(*this);
05981 
05982     if (d.occurrences == 0) {
05983         qWarning("QString::arg: Argument missing: %s, %g", toLocal8Bit().data(), a);
05984         return *this;
05985     }
05986 
05987     QString arg;
05988     if (d.occurrences > d.locale_occurrences)
05989         arg = number(a, fmt, prec);
05990 
05991     QString locale_arg;
05992     if (d.locale_occurrences > 0) {
05993         QLocale locale;
05994 
05995         QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
05996         uint flags = 0;
05997 
05998         if (qIsUpper(fmt))
05999             flags = QLocalePrivate::CapitalEorX;
06000         fmt = qToLower(fmt);
06001 
06002         switch (fmt) {
06003             case 'f':
06004                 form = QLocalePrivate::DFDecimal;
06005                 break;
06006             case 'e':
06007                 form = QLocalePrivate::DFExponent;
06008                 break;
06009             case 'g':
06010                 form = QLocalePrivate::DFSignificantDigits;
06011                 break;
06012             default:
06013 #if defined(QT_CHECK_RANGE)
06014                 qWarning("QString::arg: Invalid format char '%c'", fmt);
06015 #endif
06016                 break;
06017         }
06018 
06019         flags |= QLocalePrivate::ThousandsGroup;
06020 
06021         locale_arg = locale.d()->doubleToString(a, prec, form, -1, flags);
06022     }
06023 
06024     return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
06025 }
06026 
06027 
06028 QString QString::multiArg(int numArgs, const QString **args) const
06029 {
06030     QString result;
06031     union {
06032         int digitUsed[10];
06033         int argForDigit[10];
06034     };
06035     const QChar *uc = (const QChar*) d->data;
06036     const int len = d->size;
06037     const int end = len - 1;
06038     int lastDigit = -1;
06039     int i;
06040 
06041     memset(digitUsed, 0, sizeof(digitUsed));
06042 
06043     for (i = 0; i < end; i++) {
06044         if (uc[i] == QLatin1Char('%')) {
06045             int digit = uc[i + 1].unicode() - '0';
06046             if (digit >= 0 && digit <= 9)
06047                 digitUsed[digit]++;
06048         }
06049     }
06050 
06051     for (i = 0; i < numArgs; i++) {
06052         do {
06053             ++lastDigit;
06054         } while (lastDigit < 10 && digitUsed[lastDigit] == 0);
06055 
06056         if (lastDigit == 10) {
06057             qWarning("QString::arg: Argument missing: %s, %s", toLocal8Bit().data(), args[i]->toLocal8Bit().data());
06058             numArgs = i;
06059             lastDigit = 9;
06060             break;
06061         }
06062         argForDigit[lastDigit] = i;
06063     }
06064 
06065     i = 0;
06066     while (i < len) {
06067         if (uc[i] == QLatin1Char('%') && i != end) {
06068             int digit = uc[i + 1].unicode() - '0';
06069             if (digit >= 0 && digit <= lastDigit) {
06070                 result += *args[argForDigit[digit]];
06071                 i += 2;
06072                 continue;
06073             }
06074         }
06075         result += uc[i++];
06076     }
06077     return result;
06078 }
06079 
06080 
06081 
06084 void QString::updateProperties() const
06085 {
06086     ushort *p = d->data;
06087     ushort *end = p + d->size;
06088     d->simpletext = true;
06089     while (p < end) {
06090         ushort uc = *p;
06091         // sort out regions of complex text formatting
06092         if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) {
06093             d->simpletext = false;
06094         }
06095         p++;
06096     }
06097 
06098     p = d->data;
06099     d->righttoleft = false;
06100     while (p < end) {
06101         switch(QUnicodeTables::direction(*p))
06102         {
06103         case QChar::DirL:
06104         case QChar::DirLRO:
06105         case QChar::DirLRE:
06106             goto end;
06107         case QChar::DirR:
06108         case QChar::DirAL:
06109         case QChar::DirRLO:
06110         case QChar::DirRLE:
06111             d->righttoleft = true;
06112             goto end;
06113         default:
06114             break;
06115         }
06116         ++p;
06117     }
06118  end:
06119     d->clean = true;
06120     return;
06121 }
06122 
06253 QString QString::fromRawData(const QChar *unicode, int size)
06254 {
06255     Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
06256     if (unicode) {
06257         x->data = (ushort *)unicode;
06258     } else {
06259         x->data = x->array;
06260         size = 0;
06261     }
06262     x->ref.init(1);
06263     x->alloc = x->size = size;
06264     *x->array = '\0';
06265     x->clean = x->asciiCache = x->simpletext = x->righttoleft = 0;
06266     return QString(x, 0);
06267 }
06268 
06424 #ifndef QT_NO_DATASTREAM
06425 
06434 QDataStream &operator<<(QDataStream &out, const QString &str)
06435 {
06436     if (out.version() == 1) {
06437         out << str.toLatin1();
06438     } else {
06439         if (!str.isNull() || out.version() < 3) {
06440             int byteOrder = out.byteOrder();
06441             const QChar* ub = str.unicode();
06442             static const uint auto_size = 1024;
06443             char t[auto_size];
06444             char *b;
06445             if (str.length()*sizeof(QChar) > auto_size) {
06446                 b = new char[str.length()*sizeof(QChar)];
06447             } else {
06448                 b = t;
06449             }
06450             int l = str.length();
06451             char *c=b;
06452             while (l--) {
06453                 if (byteOrder == QDataStream::BigEndian) {
06454                     *c++ = (char)ub->row();
06455                     *c++ = (char)ub->cell();
06456                 } else {
06457                     *c++ = (char)ub->cell();
06458                     *c++ = (char)ub->row();
06459                 }
06460                 ub++;
06461             }
06462             out.writeBytes(b, sizeof(QChar)*str.length());
06463             if (str.length()*sizeof(QChar) > auto_size)
06464                 delete [] b;
06465         } else {
06466             // write null marker
06467             out << (quint32)0xffffffff;
06468         }
06469     }
06470     return out;
06471 }
06472 
06482 QDataStream &operator>>(QDataStream &in, QString &str)
06483 {
06484 #ifdef QT_QSTRING_UCS_4
06485 #if defined(Q_CC_GNU)
06486 #warning "operator>> not working properly"
06487 #endif
06488 #endif
06489 
06490     if (in.version() == 1) {
06491         QByteArray l;
06492         in >> l;
06493         str = QString::fromLatin1(l);
06494     } else {
06495         quint32 bytes = 0;
06496         in >> bytes;                                  // read size of string
06497         if (bytes == 0xffffffff) {                    // null string
06498             str.clear();
06499         } else if (bytes > 0) {                       // not empty
06500             if (bytes & 0x1) {
06501                 str.clear();
06502                 in.setStatus(QDataStream::ReadCorruptData);
06503                 return in;
06504             }
06505 
06506             const quint32 Step = 1024 * 1024;
06507             quint32 len = bytes / 2;
06508             quint32 allocated = 0;
06509 
06510             while (allocated < len) {
06511                 int blockSize = qMin(Step, len - allocated);
06512                 str.resize(allocated + blockSize);
06513                 if (in.readRawData(reinterpret_cast<char *>(str.data()) + allocated * 2,
06514                                    blockSize * 2) != blockSize * 2) {
06515                     str.clear();
06516                     in.setStatus(QDataStream::ReadPastEnd);
06517                     return in;
06518                 }
06519                 allocated += blockSize;
06520             }
06521 
06522             if ((in.byteOrder() == QDataStream::BigEndian)
06523                     != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
06524                 ushort *data = reinterpret_cast<ushort *>(str.data());
06525                 while (len--) {
06526                     *data = (*data >> 8) | (*data << 8);
06527                     ++data;
06528                 }
06529             }
06530         } else {
06531             str = QLatin1String("");
06532         }
06533     }
06534     return in;
06535 }
06536 #endif // QT_NO_DATASTREAM
06537 

Generated on Thu Mar 15 11:54:13 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1