diff options
Diffstat (limited to 'src/corelib/tools/qstring.cpp')
-rw-r--r-- | src/corelib/tools/qstring.cpp | 325 |
1 files changed, 174 insertions, 151 deletions
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ad44228039..4262899e02 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -81,9 +81,6 @@ #ifdef Q_OS_WIN # include <qt_windows.h> -# ifdef Q_OS_WINCE -# include <winnls.h> -# endif #endif #ifdef truncate @@ -449,6 +446,16 @@ extern "C" int qt_ucstrncmp_mips_dsp_asm(const ushort *a, // Unicode case-sensitive compare two same-sized strings static int ucstrncmp(const QChar *a, const QChar *b, int l) { +#ifdef __OPTIMIZE_SIZE__ + const QChar *end = a + l; + while (a < end) { + if (int diff = (int)a->unicode() - (int)b->unicode()) + return diff; + ++a; + ++b; + } + return 0; +#else #if defined(__mips_dsp) if (l >= 8) { return qt_ucstrncmp_mips_dsp_asm(reinterpret_cast<const ushort*>(a), @@ -471,12 +478,12 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l) uint mask = ~_mm_movemask_epi8(result); if (ushort(mask)) { // found a different byte - uint idx = uint(_bit_scan_forward(mask)); + uint idx = qCountTrailingZeroBits(mask); return reinterpret_cast<const QChar *>(ptr + idx)->unicode() - reinterpret_cast<const QChar *>(ptr + distance + idx)->unicode(); } } -# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__) +# if defined(Q_COMPILER_LAMBDA) const auto &lambda = [=](int i) -> int { return reinterpret_cast<const QChar *>(ptr)[i].unicode() - reinterpret_cast<const QChar *>(ptr + distance)[i].unicode(); @@ -530,6 +537,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l) } } return 0; +#endif } static int ucstrncmp(const QChar *a, const uchar *c, int l) @@ -572,7 +580,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l) # endif if (mask) { // found a different character - uint idx = uint(_bit_scan_forward(mask)); + uint idx = qCountTrailingZeroBits(mask); return uc[offset + idx / 2] - c[offset + idx / 2]; } } @@ -590,7 +598,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l) uint mask = ~_mm_movemask_epi8(result); if (ushort(mask)) { // found a different character - uint idx = uint(_bit_scan_forward(mask)); + uint idx = qCountTrailingZeroBits(mask); return uc[offset + idx / 2] - c[offset + idx / 2]; } @@ -685,7 +693,7 @@ static int findChar(const QChar *str, int len, QChar ch, int from, // found a match // same as: return n - s + _bit_scan_forward(mask) / 2 return (reinterpret_cast<const char *>(n) - reinterpret_cast<const char *>(s) - + _bit_scan_forward(mask)) >> 1; + + qCountTrailingZeroBits(mask)) >> 1; } } @@ -1150,7 +1158,7 @@ const QString::Null QString::null = { }; has a ref count of 1, whereas QString::append() needs an extra test). - There are three ways you can access this improved method of string + There are two ways you can access this improved method of string construction. The straightforward way is to include \c{QStringBuilder} wherever you want to use it, and use the \c{'%'} operator instead of \c{'+'} when concatenating strings: @@ -2292,21 +2300,20 @@ QString &QString::remove(const QString &str, Qt::CaseSensitivity cs) */ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs) { - int i = 0; - ushort c = ch.unicode(); - if (cs == Qt::CaseSensitive) { - while (i < d->size) - if (d->data()[i] == ch) - remove(i, 1); - else - i++; - } else { - c = foldCase(c); - while (i < d->size) - if (foldCase(d->data()[i]) == c) - remove(i, 1); - else - i++; + const int idx = indexOf(ch, 0, cs); + if (idx != -1) { + const auto first = begin(); // implicit detach() + auto last = end(); + if (cs == Qt::CaseSensitive) { + last = std::remove(first + idx, last, ch); + } else { + const QChar c = ch.toCaseFolded(); + auto caseInsensEqual = [c](QChar x) { + return c == x.toCaseFolded(); + }; + last = std::remove_if(first + idx, last, caseInsensEqual); + } + resize(last - first); } return *this; } @@ -2625,21 +2632,28 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs */ QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs) { - ushort a = after.unicode(); - ushort b = before.unicode(); if (d->size) { - detach(); - ushort *i = d->data(); - const ushort *e = i + d->size; - if (cs == Qt::CaseSensitive) { - for (; i != e; ++i) - if (*i == b) - *i = a; - } else { - b = foldCase(b); - for (; i != e; ++i) - if (foldCase(*i) == b) - *i = a; + const int idx = indexOf(before, 0, cs); + if (idx != -1) { + detach(); + const ushort a = after.unicode(); + ushort *i = d->data(); + const ushort *e = i + d->size; + i += idx; + *i = a; + if (cs == Qt::CaseSensitive) { + const ushort b = before.unicode(); + while (++i != e) { + if (*i == b) + *i = a; + } + } else { + const ushort b = foldCase(before.unicode()); + while (++i != e) { + if (foldCase(*i) == b) + *i = a; + } + } } } return *this; @@ -3264,22 +3278,7 @@ static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *nee */ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - const int sl = str.d->size; - if (sl == 1) - return lastIndexOf(QChar(str.d->data()[0]), from, cs); - - const int l = d->size; - if (from < 0) - from += l; - int delta = l-sl; - if (from == l && sl == 0) - return from; - if (uint(from) >= uint(l) || delta < 0) - return -1; - if (from > delta) - from = delta; - - return lastIndexOfHelper(d->data(), from, str.d->data(), str.d->size, cs); + return QStringRef(this).lastIndexOf(QStringRef(&str), from, cs); } /*! @@ -3303,25 +3302,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c */ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - const int sl = str.size(); - if (sl == 1) - return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); - - const int l = d->size; - if (from < 0) - from += l; - int delta = l-sl; - if (from == l && sl == 0) - return from; - if (uint(from) >= uint(l) || delta < 0) - return -1; - if (from > delta) - from = delta; - - QVarLengthArray<ushort> s(sl); - qt_from_latin1(s.data(), str.latin1(), sl); - - return lastIndexOfHelper(d->data(), from, s.data(), sl, cs); + return QStringRef(this).lastIndexOf(str, from, cs); } /*! @@ -3352,23 +3333,7 @@ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const { - const int sl = str.size(); - if (sl == 1) - return lastIndexOf(str.at(0), from, cs); - - const int l = d->size; - if (from < 0) - from += l; - int delta = l - sl; - if (from == l && sl == 0) - return from; - if (uint(from) >= uint(l) || delta < 0) - return -1; - if (from > delta) - from = delta; - - return lastIndexOfHelper(d->data(), from, reinterpret_cast<const ushort*>(str.unicode()), - str.size(), cs); + return QStringRef(this).lastIndexOf(str, from, cs); } @@ -5076,7 +5041,7 @@ void QString::truncate(int pos) If you want to remove characters from the \e beginning of the string, use remove() instead. - \sa truncate(), resize(), remove() + \sa truncate(), resize(), remove(), QStringRef::chop() */ void QString::chop(int n) { @@ -5484,9 +5449,15 @@ int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_N int QString::compare_helper(const QChar *data1, int length1, const char *data2, int length2, Qt::CaseSensitivity cs) { - // ### optimize me - const QString s2 = QString::fromUtf8(data2, length2 == -1 ? (data2 ? int(strlen(data2)) : -1) : length2); - return compare_helper(data1, length1, s2.constData(), s2.size(), cs); + if (!data2) + return length1; + if (Q_UNLIKELY(length2 < 0)) + length2 = int(strlen(data2)); + // ### make me nothrow in all cases + QVarLengthArray<ushort> s2(length2); + const auto beg = reinterpret_cast<QChar *>(s2.data()); + const auto end = QUtf8::convertToUnicode(beg, data2, length2); + return compare_helper(data1, length1, beg, end - beg, cs); } /*! @@ -5587,7 +5558,7 @@ int QString::localeAwareCompare(const QString &other) const return localeAwareCompare_helper(constData(), length(), other.constData(), other.length()); } -#if defined(QT_USE_ICU) && !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE) && !defined (Q_OS_MAC) +#if defined(QT_USE_ICU) && !defined(Q_OS_WIN32) && !defined(Q_OS_DARWIN) Q_GLOBAL_STATIC(QThreadStorage<QCollator>, defaultCollator) #endif @@ -5602,12 +5573,12 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, if (length1 == 0 || length2 == 0) return ucstrcmp(data1, length1, data2, length2); -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) -#ifndef Q_OS_WINRT +#if defined(Q_OS_WIN) +# ifndef Q_OS_WINRT int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2); -#else +# else int res = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, (LPCWSTR)data1, length1, (LPCWSTR)data2, length2, NULL, NULL, 0); -#endif +# endif switch (res) { case CSTR_LESS_THAN: @@ -8014,40 +7985,6 @@ QString QString::multiArg(int numArgs, const QString **args) const return result; } - -/*! \fn QString QString::fromCFString(CFStringRef string) - \since 5.2 - - Constructs a new QString containing a copy of the \a string CFString. - - \note this function is only available on \macos and iOS. -*/ - -/*! \fn CFStringRef QString::toCFString() const - \since 5.2 - - Creates a CFString from a QString. The caller owns the CFString and is - responsible for releasing it. - - \note this function is only available on \macos and iOS. -*/ - -/*! \fn QString QString::fromNSString(const NSString *string) - \since 5.2 - - Constructs a new QString containing a copy of the \a string NSString. - - \note this function is only available on \macos and iOS. -*/ - -/*! \fn NSString QString::toNSString() const - \since 5.2 - - Creates a NSString from a QString. The NSString is autoreleased. - - \note this function is only available on \macos and iOS. -*/ - /*! \fn bool QString::isSimpleText() const \internal @@ -8397,6 +8334,78 @@ QString &QString::setRawData(const QChar *unicode, int size) Returns the size of the Latin-1 string stored in this object. */ +/*! \fn QLatin1Char QLatin1String::at(int pos) const + \since 5.8 + + Returns the character at position \a pos in this object. + + \note This function performs no error checking. + The behavior is undefined when \a pos < 0 or \a pos ≥ size(). + + \sa operator[]() +*/ + +/*! \fn QLatin1Char QLatin1String::operator[](int pos) const + \since 5.8 + + Returns the character at position \a pos in this object. + + \note This function performs no error checking. + The behavior is undefined when \a pos < 0 or \a pos ≥ size(). + + \sa at() +*/ + +/*! \fn QLatin1String QLatin1String::mid(int start) const + \since 5.8 + + Returns the substring starting at position \a start in this object, + and extending to the end of the string. + + \note This function performs no error checking. + The behavior is undefined when \a start < 0 or \a start > size(). + + \sa left(), right() +*/ + +/*! \fn QLatin1String QLatin1String::mid(int start, int length) const + \since 5.8 + \overload + + Returns the substring of length \a length starting at position + \a start in this object. + + \note This function performs no error checking. + The behavior is undefined when \a start < 0, \a length < 0, + or \a start + \a length > size(). + + \sa left(), right() +*/ + +/*! \fn QLatin1String QLatin1String::left(int length) const + \since 5.8 + + Returns the substring of length \a length starting at position + 0 in this object. + + \note This function performs no error checking. + The behavior is undefined when \a length < 0 or \a length > size(). + + \sa mid(), right() +*/ + +/*! \fn QLatin1String QLatin1String::right(int length) const + \since 5.8 + + Returns the substring of length \a length starting at position + size() - \a length in this object. + + \note This function performs no error checking. + The behavior is undefined when \a length < 0 or \a length > size(). + + \sa mid(), left() +*/ + /*! \fn bool QLatin1String::operator==(const QString &other) const Returns \c true if this string is equal to string \a other; @@ -9429,6 +9438,24 @@ QStringRef QStringRef::appendTo(QString *string) const */ /*! + \overload + \fn int QStringRef::compare(const QByteArray &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 5.8 + + Compares this string with \a other and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other byte array, + interpreted as a UTF-8 sequence. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. + + Equivalent to \c {compare(*this, other, cs)}. + + \sa QString::compare() +*/ + +/*! \fn int QStringRef::localeAwareCompare(const QStringRef &s1, const QString & s2) \since 4.5 @@ -9671,6 +9698,18 @@ QStringRef QString::midRef(int position, int n) const */ /*! + \fn void QStringRef::chop(int n) + \since 5.8 + + Removes \a n characters from the end of the string. + + If \a n is greater than or equal to size(), the result is an + empty string; if \a n is negative, it is equivalent to passing zero. + + \sa QString::chop(), truncate() +*/ + +/*! \since 4.8 Returns the index position of the first occurrence of the string \a @@ -9760,23 +9799,7 @@ int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) */ int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - const int sl = str.size(); - if (sl == 1) - return lastIndexOf(str.at(0), from, cs); - - const int l = size();; - if (from < 0) - from += l; - int delta = l - sl; - if (from == l && sl == 0) - return from; - if (uint(from) >= uint(l) || delta < 0) - return -1; - if (from > delta) - from = delta; - - return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, - reinterpret_cast<const ushort*>(str.unicode()), str.size(), cs); + return lastIndexOf(QStringRef(&str), from, cs); } /*! @@ -9812,7 +9835,7 @@ int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) { const int sl = str.size(); if (sl == 1) - return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); + return lastIndexOf(str.at(0), from, cs); const int l = size(); if (from < 0) |