00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
01336 } else if (pos + len >= d->size) {
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
01509
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
01547
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
01558 if (!bl)
01559 index++;
01560 }
01561 if (!pos)
01562 break;
01563
01564
01565 int adjust = pos*(al-bl);
01566
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
01979
01980
01981
01982 if (l > 500 && sl > 5)
01983 return QStringMatcher(str, cs).indexIn(*this, from);
01984
01985
01986
01987
01988
01989
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
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
02228
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
02261 index++;
02262 }
02263 caretMode = QRegExp::CaretWontMatch;
02264 }
02265 delete[] capturePositions;
02266 delete[] captureNumbers;
02267 return *this;
02268 }
02269 }
02270
02271
02272
02273
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
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
02302
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) {
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 ®, 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 §ion = 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 §ion = 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 §ion = 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
03037
03038
03039
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
03224 } else {
03225 #ifndef QT_NO_DEBUG
03226
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
03259 }
03260 } else {
03261
03262 qWarning("MultiByteToWideChar: Cannot convert multibyte text");
03263 break;
03264 }
03265 }
03266 if (len <= 0)
03267 return QString();
03268 if (wc[len-1] == 0)
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);
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
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
03378
03379
03380
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
03404 qch = addOne(qch, result);
03405 *qch++ = 0xdbff;
03406 *qch++ = 0xde00 + ((uchar)str[i]);
03407 }
03408 }
03409 }
03410 if (need) {
03411
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);
03470 QChar *uc = s.data();
03471 for (int i = 0; i < size; ++i) {
03472 uint u = unicode[i];
03473 if (u > 0xffff) {
03474
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())
03589 start++;
03590 if (start <= end) {
03591 while (end && s[end].isSpace())
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
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
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();
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
04460 *this = fromLatin1("");
04461 return *this;
04462 }
04463
04464
04465
04466 QString result;
04467 const char *c = cformat;
04468 for (;;) {
04469
04470 while (*c != '\0' && *c != '%')
04471 result.append(QLatin1Char(*c++));
04472
04473 if (*c == '\0')
04474 break;
04475
04476
04477 const char *escape_start = c;
04478 ++c;
04479
04480 if (*c == '\0') {
04481 result.append(QLatin1Char('%'));
04482 break;
04483 }
04484 if (*c == '%') {
04485 result.append(QLatin1Char('%'));
04486 ++c;
04487 continue;
04488 }
04489
04490
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));
04510 break;
04511 }
04512
04513
04514 int width = -1;
04515 if (qIsDigit(*c)) {
04516 QString width_str;
04517 while (*c != '\0' && qIsDigit(*c))
04518 width_str.append(QLatin1Char(*c++));
04519
04520
04521
04522 width = width_str.toInt();
04523 }
04524 else if (*c == '*') {
04525 width = va_arg(ap, int);
04526 if (width < 0)
04527 width = -1;
04528 ++c;
04529 }
04530
04531 if (*c == '\0') {
04532 result.append(QLatin1String(escape_start));
04533 break;
04534 }
04535
04536
04537 int precision = -1;
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
04546
04547 precision = precision_str.toInt();
04548 }
04549 else if (*c == '*') {
04550 precision = va_arg(ap, int);
04551 if (precision < 0)
04552 precision = -1;
04553 ++c;
04554 }
04555 }
04556
04557 if (*c == '\0') {
04558 result.append(QLatin1String(escape_start));
04559 break;
04560 }
04561
04562
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));
04612 break;
04613 }
04614
04615
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);
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':
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();
04750 *n = tmp;
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:
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;
05542 int occurrences;
05543 int locale_occurrences;
05544
05545 int escape_len;
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
05630
05631
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) {
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) {
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
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
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;
06497 if (bytes == 0xffffffff) {
06498 str.clear();
06499 } else if (bytes > 0) {
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