diff options
Diffstat (limited to 'src/corelib/text/qstring.cpp')
-rw-r--r-- | src/corelib/text/qstring.cpp | 520 |
1 files changed, 194 insertions, 326 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 82b2c10a93..51d383ea18 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -100,7 +100,7 @@ #define ULLONG_MAX quint64_C(18446744073709551615) #endif -#define IS_RAW_DATA(d) ((d)->offset != sizeof(QStringData)) +#define IS_RAW_DATA(d) ((d.d)->flags & QArrayData::RawDataType) QT_BEGIN_NAMESPACE @@ -163,7 +163,7 @@ qsizetype QtPrivate::qustrlen(const ushort *str) noexcept { qsizetype result = 0; -#ifdef __SSE2__ +#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || QT_HAS_FEATURE(address_sanitizer)) // find the 16-byte alignment immediately prior or equal to str quintptr misalignment = quintptr(str) & 0xf; Q_ASSERT((misalignment & 1) == 0); @@ -1377,28 +1377,6 @@ const QString::Null QString::null = { }; */ /*! - \class QCharRef - \inmodule QtCore - \reentrant - \brief The QCharRef class is a helper class for QString. - - \internal - - \ingroup string-processing - - When you get an object of type QCharRef, if you can assign to it, - the assignment will apply to the character in the string from - which you got the reference. That is its whole purpose in life. - The QCharRef becomes invalid once modifications are made to the - string: if you want to keep the character, copy it into a QChar. - - Most of the QChar member functions also exist in QCharRef. - However, they are not explicitly documented here. - - \sa QString::operator[](), QString::at(), QChar -*/ - -/*! \class QString \inmodule QtCore \reentrant @@ -2117,8 +2095,8 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out) */ QString::QString(const QChar *unicode, int size) { - if (!unicode) { - d = Data::sharedNull(); + if (!unicode) { + d.clear(); } else { if (size < 0) { size = 0; @@ -2126,13 +2104,11 @@ QString::QString(const QChar *unicode, int size) ++size; } if (!size) { - d = Data::allocate(0); + d = DataPointer(Data::allocate(0), 0); } else { - d = Data::allocate(size + 1); - Q_CHECK_PTR(d); - d->size = size; - memcpy(d->data(), unicode, size * sizeof(QChar)); - d->data()[size] = '\0'; + d = DataPointer(Data::allocate(size + 1), size); + memcpy(d.data(), unicode, size * sizeof(QChar)); + d.data()[size] = '\0'; } } } @@ -2145,15 +2121,13 @@ QString::QString(const QChar *unicode, int size) */ QString::QString(int size, QChar ch) { - if (size <= 0) { - d = Data::allocate(0); + if (size <= 0) { + d = DataPointer(Data::allocate(0), 0); } else { - d = Data::allocate(size + 1); - Q_CHECK_PTR(d); - d->size = size; - d->data()[size] = '\0'; - ushort *i = d->data() + size; - ushort *b = d->data(); + d = DataPointer(Data::allocate(size + 1), size); + d.data()[size] = '\0'; + ushort *i = d.data() + size; + ushort *b = d.data(); const ushort value = ch.unicode(); while (i != b) *--i = value; @@ -2168,10 +2142,8 @@ QString::QString(int size, QChar ch) */ QString::QString(int size, Qt::Initialization) { - d = Data::allocate(size + 1); - Q_CHECK_PTR(d); - d->size = size; - d->data()[size] = '\0'; + d = DataPointer(Data::allocate(size + 1), size); + d.data()[size] = '\0'; } /*! \fn QString::QString(QLatin1String str) @@ -2186,11 +2158,9 @@ QString::QString(int size, Qt::Initialization) */ QString::QString(QChar ch) { - d = Data::allocate(2); - Q_CHECK_PTR(d); - d->size = 1; - d->data()[0] = ch.unicode(); - d->data()[1] = '\0'; + d = DataPointer(Data::allocate(2), 1); + d.data()[0] = ch.unicode(); + d.data()[1] = '\0'; } /*! \fn QString::QString(const QByteArray &ba) @@ -2212,7 +2182,7 @@ QString::QString(QChar ch) \internal */ -/*! \fn QString::QString(QStringDataPtr) +/*! \fn QString::QString(QStringPrivate) \internal */ @@ -2282,16 +2252,16 @@ void QString::resize(int size) if (size < 0) size = 0; - if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) { - d->size = size; + if (!d->isShared() && !d->isMutable() && size < int(d.size)) { + d.size = size; return; } - if (d->ref.isShared() || uint(size) + 1u > d->alloc) + if (d->needsDetach() || size > capacity()) reallocData(uint(size) + 1u, true); - if (d->alloc) { - d->size = size; - d->data()[size] = '\0'; + d.size = size; + if (d->isMutable()) { + d.data()[size] = '\0'; } } @@ -2311,7 +2281,7 @@ void QString::resize(int size, QChar fillChar) resize(size); const int difference = length() - oldSize; if (difference > 0) - std::fill_n(d->begin() + oldSize, difference, fillChar.unicode()); + std::fill_n(d.data() + oldSize, difference, fillChar.unicode()); } /*! \fn int QString::capacity() const @@ -2368,28 +2338,22 @@ void QString::reallocData(uint alloc, bool grow) { auto allocOptions = d->detachFlags(); if (grow) - allocOptions |= QArrayData::Grow; - - if (d->ref.isShared() || IS_RAW_DATA(d)) { - Data *x = Data::allocate(alloc, allocOptions); - Q_CHECK_PTR(x); - x->size = qMin(int(alloc) - 1, d->size); - ::memcpy(x->data(), d->data(), x->size * sizeof(QChar)); - x->data()[x->size] = 0; - if (!d->ref.deref()) - Data::deallocate(d); - d = x; + allocOptions |= QArrayData::GrowsForward; + + if (d->needsDetach()) { + DataPointer dd(Data::allocate(alloc, allocOptions), qMin(int(alloc) - 1, d.size)); + ::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar)); + dd.data()[dd.size] = 0; + d = dd; } else { - Data *p = Data::reallocateUnaligned(d, alloc, allocOptions); - Q_CHECK_PTR(p); - d = p; + d.reallocate(alloc, allocOptions); } } #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) void QString::expand(int i) { - resize(qMax(i + 1, d->size), QLatin1Char(' ')); + resize(qMax(i + 1, size()), QLatin1Char(' ')); } #endif @@ -2408,9 +2372,6 @@ void QString::expand(int i) QString &QString::operator=(const QString &other) noexcept { - other.d->ref.ref(); - if (!d->ref.deref()) - Data::deallocate(d); d = other.d; return *this; } @@ -2432,9 +2393,9 @@ QString &QString::operator=(const QString &other) noexcept QString &QString::operator=(QLatin1String other) { if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 -> !isDetached() (sharedNull) - d->size = other.size(); - d->data()[other.size()] = 0; - qt_from_latin1(d->data(), other.latin1(), other.size()); + d.size = other.size(); + d.data()[other.size()] = 0; + qt_from_latin1(d.data(), other.latin1(), other.size()); } else { *this = fromLatin1(other.latin1(), other.size()); } @@ -2497,10 +2458,9 @@ QString &QString::operator=(QChar ch) { if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 -> !isDetached() (sharedNull) // re-use existing capacity: - ushort *dat = d->data(); - dat[0] = ch.unicode(); - dat[1] = 0; - d->size = 1; + d.data()[0] = ch.unicode(); + d.data()[1] = 0; + d.size = 1; } else { operator=(QString(ch)); } @@ -2586,13 +2546,13 @@ QString &QString::insert(int i, QLatin1String str) return *this; int len = str.size(); - if (Q_UNLIKELY(i > d->size)) + if (Q_UNLIKELY(i > size())) resize(i + len, QLatin1Char(' ')); else - resize(d->size + len); + resize(size() + len); - ::memmove(d->data() + i + len, d->data() + i, (d->size - i - len) * sizeof(QChar)); - qt_from_latin1(d->data() + i, s, uint(len)); + ::memmove(d.data() + i + len, d.data() + i, (d.size - i - len) * sizeof(QChar)); + qt_from_latin1(d.data() + i, s, uint(len)); return *this; } @@ -2609,7 +2569,7 @@ QString& QString::insert(int i, const QChar *unicode, int size) return *this; const ushort *s = (const ushort *)unicode; - if (s >= d->data() && s < d->data() + d->alloc) { + if (s >= d.data() && s < d.data() + d.size) { // Part of me - take a copy ushort *tmp = static_cast<ushort *>(::malloc(size * sizeof(QChar))); Q_CHECK_PTR(tmp); @@ -2619,13 +2579,13 @@ QString& QString::insert(int i, const QChar *unicode, int size) return *this; } - if (Q_UNLIKELY(i > d->size)) + if (Q_UNLIKELY(i > int(d.size))) resize(i + size, QLatin1Char(' ')); else - resize(d->size + size); + resize(d.size + size); - ::memmove(d->data() + i + size, d->data() + i, (d->size - i - size) * sizeof(QChar)); - memcpy(d->data() + i, s, size * sizeof(QChar)); + ::memmove(d.data() + i + size, d.data() + i, (d.size - i - size) * sizeof(QChar)); + memcpy(d.data() + i, s, size * sizeof(QChar)); return *this; } @@ -2639,15 +2599,15 @@ QString& QString::insert(int i, const QChar *unicode, int size) QString& QString::insert(int i, QChar ch) { if (i < 0) - i += d->size; + i += d.size; if (i < 0) return *this; - if (Q_UNLIKELY(i > d->size)) + if (Q_UNLIKELY(i > size())) resize(i + 1, QLatin1Char(' ')); else - resize(d->size + 1); - ::memmove(d->data() + i + 1, d->data() + i, (d->size - i - 1) * sizeof(QChar)); - d->data()[i] = ch.unicode(); + resize(d.size + 1); + ::memmove(d.data() + i + 1, d.data() + i, (d.size - i - 1) * sizeof(QChar)); + d.data()[i] = ch.unicode(); return *this; } @@ -2671,15 +2631,15 @@ QString& QString::insert(int i, QChar ch) */ QString &QString::append(const QString &str) { - if (str.d != Data::sharedNull()) { - if (d == Data::sharedNull()) { + if (!str.isNull()) { + if (isNull()) { operator=(str); } else { - if (d->ref.isShared() || uint(d->size + str.d->size) + 1u > d->alloc) - reallocData(uint(d->size + str.d->size) + 1u, true); - memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar)); - d->size += str.d->size; - d->data()[d->size] = '\0'; + if (d->needsDetach() || size() + str.size() > capacity()) + reallocData(uint(size() + str.size()) + 1u, true); + memcpy(d.data() + d.size, str.d.data(), str.d.size * sizeof(QChar)); + d.size += str.d.size; + d.data()[d.size] = '\0'; } } return *this; @@ -2694,11 +2654,11 @@ QString &QString::append(const QString &str) QString &QString::append(const QChar *str, int len) { if (str && len > 0) { - if (d->ref.isShared() || uint(d->size + len) + 1u > d->alloc) - reallocData(uint(d->size + len) + 1u, true); - memcpy(d->data() + d->size, str, len * sizeof(QChar)); - d->size += len; - d->data()[d->size] = '\0'; + if (d->needsDetach() || size() + len > capacity()) + reallocData(uint(size() + len) + 1u, true); + memcpy(d.data() + d.size, str, len * sizeof(QChar)); + d.size += len; + d.data()[d.size] = '\0'; } return *this; } @@ -2713,12 +2673,12 @@ QString &QString::append(QLatin1String str) const char *s = str.latin1(); if (s) { int len = str.size(); - if (d->ref.isShared() || uint(d->size + len) + 1u > d->alloc) - reallocData(uint(d->size + len) + 1u, true); - ushort *i = d->data() + d->size; + if (d->needsDetach() || size() + len > capacity()) + reallocData(uint(size() + len) + 1u, true); + ushort *i = d.data() + d.size; qt_from_latin1(i, s, uint(len)); i[len] = '\0'; - d->size += len; + d.size += len; } return *this; } @@ -2760,10 +2720,10 @@ QString &QString::append(QLatin1String str) */ QString &QString::append(QChar ch) { - if (d->ref.isShared() || uint(d->size) + 2u > d->alloc) - reallocData(uint(d->size) + 2u, true); - d->data()[d->size++] = ch.unicode(); - d->data()[d->size] = '\0'; + if (d->needsDetach() || size() + 1 > capacity()) + reallocData(uint(d.size) + 2u, true); + d.data()[d.size++] = ch.unicode(); + d.data()[d.size] = '\0'; return *this; } @@ -2856,16 +2816,16 @@ QString &QString::append(QChar ch) QString &QString::remove(int pos, int len) { if (pos < 0) // count from end of string - pos += d->size; - if (uint(pos) >= uint(d->size)) { + pos += size(); + if (uint(pos) >= uint(size())) { // range problems - } else if (len >= d->size - pos) { + } else if (len >= size() - pos) { resize(pos); // truncate } else if (len > 0) { detach(); - memmove(d->data() + pos, d->data() + pos + len, - (d->size - pos - len + 1) * sizeof(ushort)); - d->size -= len; + memmove(d.data() + pos, d.data() + pos + len, + (d.size - pos - len + 1) * sizeof(ushort)); + d.size -= len; } return *this; } @@ -3010,10 +2970,10 @@ QString &QString::replace(int pos, int len, const QString &after) */ QString &QString::replace(int pos, int len, const QChar *unicode, int size) { - if (uint(pos) > uint(d->size)) + if (uint(pos) > uint(this->size())) return *this; - if (len > d->size - pos) - len = d->size - pos; + if (len > this->size() - pos) + len = this->size() - pos; uint index = pos; replace_helper(&index, 1, len, unicode, size); @@ -3077,10 +3037,10 @@ bool pointsIntoRange(const QChar *ptr, const ushort *base, int len) */ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen) { - // Copy after if it lies inside our own d->data() area (which we could + // Copy after if it lies inside our own d.b area (which we could // possibly invalidate via a realloc or modify by replacement). QChar *afterBuffer = nullptr; - if (pointsIntoRange(after, d->data(), d->size)) // Use copy in place of vulnerable original: + if (pointsIntoRange(after, d.data(), d.size)) // Use copy in place of vulnerable original: after = afterBuffer = textCopy(after, alen); QT_TRY { @@ -3088,36 +3048,36 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar // replace in place detach(); for (int i = 0; i < nIndices; ++i) - memcpy(d->data() + indices[i], after, alen * sizeof(QChar)); + memcpy(d.data() + indices[i], after, alen * sizeof(QChar)); } else if (alen < blen) { // replace from front detach(); uint to = indices[0]; if (alen) - memcpy(d->data()+to, after, alen*sizeof(QChar)); + memcpy(d.data()+to, after, alen*sizeof(QChar)); to += alen; uint movestart = indices[0] + blen; for (int i = 1; i < nIndices; ++i) { int msize = indices[i] - movestart; if (msize > 0) { - memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar)); + memmove(d.data() + to, d.data() + movestart, msize * sizeof(QChar)); to += msize; } if (alen) { - memcpy(d->data() + to, after, alen * sizeof(QChar)); + memcpy(d.data() + to, after, alen * sizeof(QChar)); to += alen; } movestart = indices[i] + blen; } - int msize = d->size - movestart; + int msize = d.size - movestart; if (msize > 0) - memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar)); - resize(d->size - nIndices*(blen-alen)); + memmove(d.data() + to, d.data() + movestart, msize * sizeof(QChar)); + resize(d.size - nIndices*(blen-alen)); } else { // replace from back int adjust = nIndices*(alen-blen); - int newLen = d->size + adjust; - int moveend = d->size; + int newLen = d.size + adjust; + int moveend = d.size; resize(newLen); while (nIndices) { @@ -3125,9 +3085,9 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar int movestart = indices[nIndices] + blen; int insertstart = indices[nIndices] + nIndices*(alen-blen); int moveto = insertstart + alen; - memmove(d->data() + moveto, d->data() + movestart, + memmove(d.data() + moveto, d.data() + movestart, (moveend - movestart)*sizeof(QChar)); - memcpy(d->data() + insertstart, after, alen * sizeof(QChar)); + memcpy(d.data() + insertstart, after, alen * sizeof(QChar)); moveend = movestart-blen; } } @@ -3153,7 +3113,7 @@ QString &QString::replace(const QChar *before, int blen, const QChar *after, int alen, Qt::CaseSensitivity cs) { - if (d->size == 0) { + if (d.size == 0) { if (blen) return *this; } else { @@ -3188,10 +3148,10 @@ QString &QString::replace(const QChar *before, int blen, We're about to change data, that before and after might point into, and we'll need that data for our next batch of indices. */ - if (!afterBuffer && pointsIntoRange(after, d->data(), d->size)) + if (!afterBuffer && pointsIntoRange(after, d.data(), d.size)) after = afterBuffer = textCopy(after, alen); - if (!beforeBuffer && pointsIntoRange(before, d->data(), d->size)) { + if (!beforeBuffer && pointsIntoRange(before, d.data(), d.size)) { beforeBuffer = textCopy(before, blen); matcher = QStringMatcher(beforeBuffer, blen, cs); } @@ -3220,13 +3180,13 @@ QString &QString::replace(const QChar *before, int blen, */ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs) { - if (after.d->size == 0) + if (after.size() == 0) return remove(ch, cs); - if (after.d->size == 1) + if (after.size() == 1) return replace(ch, after.front(), cs); - if (d->size == 0) + if (size() == 0) return *this; ushort cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode()); @@ -3236,14 +3196,14 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs uint indices[1024]; uint pos = 0; if (cs == Qt::CaseSensitive) { - while (pos < 1024 && index < d->size) { - if (d->data()[index] == cc) + while (pos < 1024 && index < size()) { + if (d.data()[index] == cc) indices[pos++] = index; index++; } } else { - while (pos < 1024 && index < d->size) { - if (QChar::toCaseFolded(d->data()[index]) == cc) + while (pos < 1024 && index < size()) { + if (QChar::toCaseFolded(d.data()[index]) == cc) indices[pos++] = index; index++; } @@ -3251,12 +3211,12 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs if (!pos) // Nothing to replace break; - replace_helper(indices, pos, 1, after.constData(), after.d->size); + replace_helper(indices, pos, 1, after.constData(), after.size()); if (Q_LIKELY(index == -1)) // Nothing left to replace break; // The call to replace_helper just moved what index points at: - index += pos*(after.d->size - 1); + index += pos*(after.size() - 1); } return *this; } @@ -3271,13 +3231,13 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs */ QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs) { - if (d->size) { + if (d.size) { 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; + ushort *i = d.data(); + ushort *const e = i + d.size; i += idx; *i = a; if (cs == Qt::CaseSensitive) { @@ -3338,7 +3298,7 @@ QString &QString::replace(QLatin1String before, const QString &after, Qt::CaseSe int blen = before.size(); QVarLengthArray<ushort> b(blen); qt_from_latin1(b.data(), before.latin1(), blen); - return replace((const QChar *)b.data(), blen, after.constData(), after.d->size, cs); + return replace((const QChar *)b.data(), blen, after.constData(), after.d.size, cs); } /*! @@ -3358,7 +3318,7 @@ QString &QString::replace(const QString &before, QLatin1String after, Qt::CaseSe int alen = after.size(); QVarLengthArray<ushort> a(alen); qt_from_latin1(a.data(), after.latin1(), alen); - return replace(before.constData(), before.d->size, (const QChar *)a.data(), alen, cs); + return replace(before.constData(), before.d.size, (const QChar *)a.data(), alen, cs); } /*! @@ -3394,7 +3354,7 @@ QString &QString::replace(QChar c, QLatin1String after, Qt::CaseSensitivity cs) */ bool operator==(const QString &s1, const QString &s2) noexcept { - if (s1.d->size != s2.d->size) + if (s1.d.size != s2.d.size) return false; return qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0; @@ -3407,7 +3367,7 @@ bool operator==(const QString &s1, const QString &s2) noexcept */ bool QString::operator==(QLatin1String other) const noexcept { - if (d->size != other.size()) + if (size() != other.size()) return false; return qt_compare_strings(*this, other, Qt::CaseSensitive) == 0; @@ -3953,7 +3913,7 @@ QString& QString::replace(const QRegExp &rx, const QString &after) if (isEmpty() && rx2.indexIn(*this) == -1) return *this; - reallocData(uint(d->size) + 1u); + reallocData(uint(d.size) + 1u); int index = 0; int numCaptures = rx2.captureCount(); @@ -4052,8 +4012,8 @@ QString& QString::replace(const QRegExp &rx, const QString &after) } if (!pos) break; - replacements[pos].pos = d->size; - int newlen = d->size + adjust; + replacements[pos].pos = d.size; + int newlen = d.size + adjust; // to continue searching at the right position after we did // the first round of replacements @@ -4068,14 +4028,14 @@ QString& QString::replace(const QRegExp &rx, const QString &after) while (i < pos) { int copyend = replacements[i].pos; int size = copyend - copystart; - memcpy(static_cast<void*>(uc), static_cast<const void *>(d->data() + copystart), size * sizeof(QChar)); + memcpy(static_cast<void*>(uc), static_cast<const void *>(d.data() + copystart), size * sizeof(QChar)); uc += size; - memcpy(static_cast<void *>(uc), static_cast<const void *>(after.d->data()), al * sizeof(QChar)); + memcpy(static_cast<void *>(uc), static_cast<const void *>(after.d.data()), al * sizeof(QChar)); uc += al; copystart = copyend + replacements[i].length; i++; } - memcpy(static_cast<void *>(uc), static_cast<const void *>(d->data() + copystart), (d->size - copystart) * sizeof(QChar)); + memcpy(static_cast<void *>(uc), static_cast<const void *>(d.data() + copystart), (d.size - copystart) * sizeof(QChar)); newstring.resize(newlen); *this = newstring; caretMode = QRegExp::CaretWontMatch; @@ -4115,7 +4075,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after) if (!iterator.hasNext()) // no matches at all return *this; - reallocData(uint(d->size) + 1u); + reallocData(uint(d.size) + 1u); int numCaptures = re.captureCount(); @@ -4448,24 +4408,6 @@ int QString::count(const QRegExp& rx) const #if QT_CONFIG(regularexpression) /*! - \overload indexOf() - \since 5.0 - - Returns the index position of the first match of the regular - expression \a re in the string, searching forward from index - position \a from. Returns -1 if \a re didn't match anywhere. - - Example: - - \snippet qstring/main.cpp 93 -*/ -int QString::indexOf(const QRegularExpression& re, int from) const -{ - return indexOf(re, from, nullptr); -} - -/*! - \overload \since 5.5 Returns the index position of the first match of the regular @@ -4478,7 +4420,7 @@ int QString::indexOf(const QRegularExpression& re, int from) const Example: - \snippet qstring/main.cpp 99 + \snippet qstring/main.cpp 93 */ int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const { @@ -4499,24 +4441,6 @@ int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionM } /*! - \overload lastIndexOf() - \since 5.0 - - Returns the index position of the last match of the regular - expression \a re in the string, which starts before the index - position \a from. Returns -1 if \a re didn't match anywhere. - - Example: - - \snippet qstring/main.cpp 94 -*/ -int QString::lastIndexOf(const QRegularExpression &re, int from) const -{ - return lastIndexOf(re, from, nullptr); -} - -/*! - \overload \since 5.5 Returns the index position of the last match of the regular @@ -4529,7 +4453,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from) const Example: - \snippet qstring/main.cpp 100 + \snippet qstring/main.cpp 94 */ int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const { @@ -4556,19 +4480,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpress return lastIndex; } -/*! \overload contains() - \since 5.0 - - Returns \c true if the regular expression \a re matches somewhere in - this string; otherwise returns \c false. -*/ -bool QString::contains(const QRegularExpression &re) const -{ - return contains(re, nullptr); -} - /*! - \overload contains() \since 5.1 Returns \c true if the regular expression \a re matches somewhere in this @@ -4915,9 +4827,9 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti */ QString QString::left(int n) const { - if (uint(n) >= uint(d->size)) + if (uint(n) >= uint(size())) return *this; - return QString((const QChar*) d->data(), n); + return QString((const QChar*) d.data(), n); } /*! @@ -4933,9 +4845,9 @@ QString QString::left(int n) const */ QString QString::right(int n) const { - if (uint(n) >= uint(d->size)) + if (uint(n) >= uint(size())) return *this; - return QString((const QChar*) d->data() + d->size - n, n); + return QString(constData() + size() - n, n); } /*! @@ -4958,18 +4870,19 @@ QString QString::right(int n) const QString QString::mid(int position, int n) const { using namespace QtPrivate; - switch (QContainerImplHelper::mid(d->size, &position, &n)) { + switch (QContainerImplHelper::mid(size(), &position, &n)) { case QContainerImplHelper::Null: return QString(); case QContainerImplHelper::Empty: { - QStringDataPtr empty = { Data::allocate(0) }; + QPair<Data *, ushort *> pair = Data::allocate(0); + DataPointer empty = { pair.first, pair.second, 0 }; return QString(empty); } case QContainerImplHelper::Full: return *this; case QContainerImplHelper::Subset: - return QString((const QChar*)d->data() + position, n); + return QString(constData() + position, n); } Q_UNREACHABLE(); return QString(); @@ -5211,29 +5124,29 @@ QByteArray QString::toLatin1_helper_inplace(QString &s) // We can return our own buffer to the caller. // Conversion to Latin-1 always shrinks the buffer by half. - const ushort *data = reinterpret_cast<const ushort *>(s.constData()); - uint length = s.size(); + const ushort *data = s.d.data(); + int length = s.d.size; - // Swap the d pointers. + // Move the d pointer over to the bytearray. // Kids, avert your eyes. Don't try this at home. - QArrayData *ba_d = s.d; - // multiply the allocated capacity by sizeof(ushort) - ba_d->alloc *= sizeof(ushort); + // this relies on the fact that we use QArrayData for everything behind the scenes which has the same layout + static_assert(sizeof(QByteArray::DataPointer) == sizeof(QString::DataPointer), "sizes have to be equal"); + QByteArray::DataPointer ba_d(reinterpret_cast<QByteArray::Data *>(s.d.d_ptr()), reinterpret_cast<char *>(s.d.data()), length); + ba_d.ref(); + s.clear(); - // reset ourselves to QString() - s.d = QString().d; + char *ddata = ba_d.data(); - // do the in-place conversion - uchar *dst = reinterpret_cast<uchar *>(ba_d->data()); - qt_to_latin1(dst, data, length); - dst[length] = '\0'; + // multiply the allocated capacity by sizeof(ushort) + ba_d.d_ptr()->alloc *= sizeof(ushort); - QByteArrayDataPtr badptr = { ba_d }; - return QByteArray(badptr); + // do the in-place conversion + qt_to_latin1(reinterpret_cast<uchar *>(ddata), data, length); + ddata[length] = '\0'; + return QByteArray(ba_d); } - /*! \fn QByteArray QString::toLatin1() const @@ -5413,34 +5326,25 @@ QVector<uint> QtPrivate::convertToUcs4(QStringView string) return qt_convert_to_ucs4(string); } -QString::Data *QString::fromLatin1_helper(const char *str, int size) +QString::DataPointer QString::fromLatin1_helper(const char *str, int size) { - Data *d; + DataPointer d; if (!str) { - d = Data::sharedNull(); + // nothing to do } else if (size == 0 || (!*str && size < 0)) { - d = Data::allocate(0); + d = DataPointer(Data::allocate(0), 0); } else { if (size < 0) size = qstrlen(str); - d = Data::allocate(size + 1); - Q_CHECK_PTR(d); - d->size = size; - d->data()[size] = '\0'; - ushort *dst = d->data(); + d = DataPointer(Data::allocate(size + 1), size); + d.data()[size] = '\0'; + ushort *dst = d.data(); qt_from_latin1(dst, str, uint(size)); } return d; } -QString::Data *QString::fromAscii_helper(const char *str, int size) -{ - QString s = fromUtf8(str, size); - s.d->ref.ref(); - return s.d; -} - /*! \fn QString QString::fromLatin1(const char *str, int size) Returns a QString initialized with the first \a size characters of the Latin-1 string \a str. @@ -5483,7 +5387,8 @@ QString QString::fromLocal8Bit_helper(const char *str, int size) if (!str) return QString(); if (size == 0 || (!*str && size < 0)) { - QStringDataPtr empty = { Data::allocate(0) }; + QPair<Data *, ushort *> pair = Data::allocate(0); + QString::DataPointer empty = { pair.first, pair.second, 0 }; return QString(empty); } #if QT_CONFIG(textcodec) @@ -5653,7 +5558,7 @@ QString& QString::setUnicode(const QChar *unicode, int size) { resize(size); if (unicode && size) - memcpy(d->data(), unicode, size * sizeof(QChar)); + memcpy(d.data(), unicode, size * sizeof(QChar)); return *this; } @@ -5775,7 +5680,7 @@ QString QString::trimmed_helper(QString &str) */ /*! - \fn QCharRef QString::operator[](int position) + \fn QChar &QString::operator[](int position) Returns the character at the specified \a position in the string as a modifiable reference. @@ -5784,20 +5689,6 @@ QString QString::trimmed_helper(QString &str) \snippet qstring/main.cpp 85 - The return value is of type QCharRef, a helper class for QString. - When you get an object of type QCharRef, you can use it as if it - were a reference to a QChar. If you assign to it, the assignment will apply to - the character in the QString from which you got the reference. - - \note Before Qt 5.14 it was possible to use this operator to access - a character at an out-of-bounds position in the string, and - then assign to such a position, causing the string to be - automatically resized. Furthermore, assigning a value to the - returned QCharRef would cause a detach of the string, even if the - string has been copied in the meanwhile (and the QCharRef kept - alive while the copy was taken). These behaviors are deprecated, - and will be changed in a future version of Qt. - \sa at() */ @@ -5807,19 +5698,6 @@ QString QString::trimmed_helper(QString &str) \overload operator[]() */ -/*! \fn QCharRef QString::operator[](uint position) - -\overload operator[]() - -Returns the character at the specified \a position in the string as a -modifiable reference. -*/ - -/*! \fn const QChar QString::operator[](uint position) const - Equivalent to \c at(position). -\overload operator[]() -*/ - /*! \fn QChar QString::front() const \since 5.10 @@ -5851,7 +5729,7 @@ modifiable reference. */ /*! - \fn QCharRef QString::front() + \fn QChar &QString::front() \since 5.10 Returns a reference to the first character in the string. @@ -5866,7 +5744,7 @@ modifiable reference. */ /*! - \fn QCharRef QString::back() + \fn QChar &QString::back() \since 5.10 Returns a reference to the last character in the string. @@ -5899,7 +5777,7 @@ modifiable reference. void QString::truncate(int pos) { - if (pos < d->size) + if (pos < size()) resize(pos); } @@ -5921,7 +5799,7 @@ void QString::truncate(int pos) void QString::chop(int n) { if (n > 0) - resize(d->size - n); + resize(d.size - n); } /*! @@ -5938,10 +5816,10 @@ void QString::chop(int n) QString& QString::fill(QChar ch, int size) { - resize(size < 0 ? d->size : size); - if (d->size) { - QChar *i = (QChar*)d->data() + d->size; - QChar *b = (QChar*)d->data(); + resize(size < 0 ? d.size : size); + if (d.size) { + QChar *i = (QChar*)d.data() + d.size; + QChar *b = (QChar*)d.data(); while (i != b) *--i = ch; } @@ -6522,11 +6400,11 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, const ushort *QString::utf16() const { - if (IS_RAW_DATA(d)) { + if (!d->isMutable()) { // ensure '\0'-termination for ::fromRawData strings - const_cast<QString*>(this)->reallocData(uint(d->size) + 1u); + const_cast<QString*>(this)->reallocData(uint(d.size) + 1u); } - return d->data(); + return d.data(); } /*! @@ -6555,8 +6433,8 @@ QString QString::leftJustified(int width, QChar fill, bool truncate) const if (padlen > 0) { result.resize(len+padlen); if (len) - memcpy(result.d->data(), d->data(), sizeof(QChar)*len); - QChar *uc = (QChar*)result.d->data() + len; + memcpy(result.d.data(), d.data(), sizeof(QChar)*len); + QChar *uc = (QChar*)result.d.data() + len; while (padlen--) * uc++ = fill; } else { @@ -6593,11 +6471,11 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const int padlen = width - len; if (padlen > 0) { result.resize(len+padlen); - QChar *uc = (QChar*)result.d->data(); + QChar *uc = (QChar*)result.d.data(); while (padlen--) * uc++ = fill; if (len) - memcpy(static_cast<void *>(uc), static_cast<const void *>(d->data()), sizeof(QChar)*len); + memcpy(static_cast<void *>(uc), static_cast<const void *>(d.data()), sizeof(QChar)*len); } else { if (truncate) result = left(width); @@ -8006,7 +7884,7 @@ QVector<QStringRef> QString::splitRef(const QRegularExpression &re, SplitBehavio */ QString QString::repeated(int times) const { - if (d->size == 0) + if (d.size == 0) return *this; if (times <= 1) { @@ -8015,27 +7893,27 @@ QString QString::repeated(int times) const return QString(); } - const int resultSize = times * d->size; + const int resultSize = times * d.size; QString result; result.reserve(resultSize); - if (result.d->alloc != uint(resultSize) + 1u) + if (result.capacity() != resultSize) return QString(); // not enough memory - memcpy(result.d->data(), d->data(), d->size * sizeof(ushort)); + memcpy(result.d.data(), d.data(), d.size * sizeof(ushort)); - int sizeSoFar = d->size; - ushort *end = result.d->data() + sizeSoFar; + int sizeSoFar = d.size; + ushort *end = result.d.data() + sizeSoFar; const int halfResultSize = resultSize >> 1; while (sizeSoFar <= halfResultSize) { - memcpy(end, result.d->data(), sizeSoFar * sizeof(ushort)); + memcpy(end, result.d.data(), sizeSoFar * sizeof(ushort)); end += sizeSoFar; sizeSoFar <<= 1; } - memcpy(end, result.d->data(), (resultSize - sizeSoFar) * sizeof(ushort)); - result.d->data()[resultSize] = '\0'; - result.d->size = resultSize; + memcpy(end, result.d.data(), (resultSize - sizeSoFar) * sizeof(ushort)); + result.d.data()[resultSize] = '\0'; + result.d.size = resultSize; return result; } @@ -9035,8 +8913,8 @@ QString QtPrivate::argToQString(QLatin1String pattern, size_t n, const ArgBase * */ bool QString::isSimpleText() const { - const ushort *p = d->data(); - const ushort * const end = p + d->size; + const ushort *p = d.data(); + const ushort * const end = p + d.size; while (p < end) { ushort uc = *p; // sort out regions of complex text formatting @@ -9200,17 +9078,14 @@ bool QString::isRightToLeft() const */ QString QString::fromRawData(const QChar *unicode, int size) { - Data *x; + QString::DataPointer x; if (!unicode) { - x = Data::sharedNull(); } else if (!size) { - x = Data::allocate(0); + x = DataPointer(Data::allocate(0), 0); } else { x = Data::fromRawData(reinterpret_cast<const ushort *>(unicode), size); - Q_CHECK_PTR(x); } - QStringDataPtr dataPtr = { x }; - return QString(dataPtr); + return QString(x); } /*! @@ -9229,17 +9104,10 @@ QString QString::fromRawData(const QChar *unicode, int size) */ QString &QString::setRawData(const QChar *unicode, int size) { - if (d->ref.isShared() || d->alloc) { - *this = fromRawData(unicode, size); - } else { - if (unicode) { - d->size = size; - d->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(d); - } else { - d->offset = sizeof(QStringData); - d->size = 0; - } + if (!unicode || !size) { + clear(); } + *this = fromRawData(unicode, size); return *this; } @@ -10538,7 +10406,7 @@ ownership of it, no memory is freed when instances are destroyed. */ QString QStringRef::toString() const { - if (!m_string) + if (isNull()) return QString(); if (m_size && m_position == 0 && m_size == m_string->size()) return *m_string; |