summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qstring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qstring.cpp')
-rw-r--r--src/corelib/text/qstring.cpp520
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;