Inline the size and data pointer members in QString
I'd have preferred to use QArrayDataPointer<ushort> for QString, but that option wasn't the best one. QArrayDataPointer try to do some operations using QArrayDataOps and that would expand to unnecessary code. What's more, the existing code expected to be able to modify and access the d pointer. Instead, this commit introduces QStringPrivate (named differently from QStringData to catch potential users), which contains the three members. This POD class is also used in QJsonValue to store the "inlined" QString. QHashedString in qtdeclarative will need a similar solution. Change-Id: I33f072158e6e2cd031d4d2ffc81f4a8dbaf4e616 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
b42a2b3c33
commit
746ab4bbd6
@ -66,7 +66,7 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
|
||||
case QJsonValue::String: {
|
||||
QString s = v.toString(parent);
|
||||
stringData = s.data_ptr();
|
||||
stringData->ref();
|
||||
stringData.d->ref();
|
||||
break;
|
||||
}
|
||||
case QJsonValue::Array:
|
||||
@ -80,9 +80,10 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
|
||||
}
|
||||
|
||||
QBinaryJsonValue::QBinaryJsonValue(QString string)
|
||||
: stringData(*reinterpret_cast<QStringData **>(&string)), t(QJsonValue::String)
|
||||
: d(nullptr), t(QJsonValue::String)
|
||||
{
|
||||
stringData->ref();
|
||||
stringData = *(QStringPrivate *)(&string);
|
||||
stringData.d->ref();
|
||||
}
|
||||
|
||||
QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonArray &a)
|
||||
@ -101,8 +102,8 @@ QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonObject &o)
|
||||
|
||||
QBinaryJsonValue::~QBinaryJsonValue()
|
||||
{
|
||||
if (t == QJsonValue::String && stringData && !stringData->deref())
|
||||
free(stringData);
|
||||
if (t == QJsonValue::String && !stringData.d->deref())
|
||||
QTypedArrayData<ushort>::deallocate(stringData.d);
|
||||
|
||||
if (d && !d->ref.deref())
|
||||
delete d;
|
||||
@ -134,9 +135,8 @@ QString QBinaryJsonValue::toString() const
|
||||
{
|
||||
if (t != QJsonValue::String)
|
||||
return QString();
|
||||
stringData->ref(); // the constructor below doesn't add a ref.
|
||||
QStringDataPtr holder = { stringData };
|
||||
return QString(holder);
|
||||
stringData.d->ref(); // the constructor below doesn't add a ref.
|
||||
return QString(stringData);
|
||||
}
|
||||
|
||||
void QBinaryJsonValue::detach()
|
||||
|
@ -85,18 +85,17 @@ public:
|
||||
~QBinaryJsonValue();
|
||||
|
||||
QBinaryJsonValue(QBinaryJsonValue &&other) noexcept
|
||||
: ui(other.ui),
|
||||
: stringData(other.stringData),
|
||||
d(other.d),
|
||||
t(other.t)
|
||||
{
|
||||
other.ui = 0;
|
||||
other.d = nullptr;
|
||||
other.t = QJsonValue::Null;
|
||||
}
|
||||
|
||||
QBinaryJsonValue &operator =(QBinaryJsonValue &&other) noexcept
|
||||
{
|
||||
qSwap(ui, other.ui);
|
||||
qSwap(stringData, other.stringData);
|
||||
qSwap(d, other.d);
|
||||
qSwap(t, other.t);
|
||||
return *this;
|
||||
@ -122,7 +121,7 @@ private:
|
||||
quint64 ui;
|
||||
bool b;
|
||||
double dbl;
|
||||
QStringData *stringData;
|
||||
QStringPrivate stringData;
|
||||
const QBinaryJsonPrivate::Base *base;
|
||||
};
|
||||
QBinaryJsonPrivate::MutableData *d = nullptr; // needed for Objects and Arrays
|
||||
|
@ -100,7 +100,7 @@
|
||||
#define ULLONG_MAX quint64_C(18446744073709551615)
|
||||
#endif
|
||||
|
||||
#define IS_RAW_DATA(d) ((d)->flags & QArrayData::RawDataType)
|
||||
#define IS_RAW_DATA(d) ((d.d)->flags & QArrayData::RawDataType)
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -2100,8 +2100,10 @@ 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.d = Data::sharedNull();
|
||||
d.b = Data::sharedNullData();
|
||||
d.size = 0;
|
||||
} else {
|
||||
if (size < 0) {
|
||||
size = 0;
|
||||
@ -2109,13 +2111,18 @@ QString::QString(const QChar *unicode, int size)
|
||||
++size;
|
||||
}
|
||||
if (!size) {
|
||||
d = Data::allocate(0).first;
|
||||
QPair<Data *, ushort *> pair = Data::allocate(0);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = 0;
|
||||
} else {
|
||||
d = Data::allocate(size + 1).first;
|
||||
Q_CHECK_PTR(d);
|
||||
d->size = size;
|
||||
memcpy(d->data(), unicode, size * sizeof(QChar));
|
||||
d->data()[size] = '\0';
|
||||
QPair<Data *, ushort *> pair = Data::allocate(size + 1);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = size;
|
||||
Q_CHECK_PTR(d.d);
|
||||
memcpy(d.b, unicode, size * sizeof(QChar));
|
||||
d.b[size] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2128,15 +2135,20 @@ QString::QString(const QChar *unicode, int size)
|
||||
*/
|
||||
QString::QString(int size, QChar ch)
|
||||
{
|
||||
if (size <= 0) {
|
||||
d = Data::allocate(0).first;
|
||||
if (size <= 0) {
|
||||
QPair<Data *, ushort *> pair = Data::allocate(0);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = 0;
|
||||
} else {
|
||||
d = Data::allocate(size + 1).first;
|
||||
Q_CHECK_PTR(d);
|
||||
d->size = size;
|
||||
d->data()[size] = '\0';
|
||||
ushort *i = d->data() + size;
|
||||
ushort *b = d->data();
|
||||
QPair<Data *, ushort *> pair = Data::allocate(size + 1);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = size;
|
||||
Q_CHECK_PTR(d.d);
|
||||
d.b[size] = '\0';
|
||||
ushort *i = d.b + size;
|
||||
ushort *b = d.b;
|
||||
const ushort value = ch.unicode();
|
||||
while (i != b)
|
||||
*--i = value;
|
||||
@ -2151,10 +2163,12 @@ QString::QString(int size, QChar ch)
|
||||
*/
|
||||
QString::QString(int size, Qt::Initialization)
|
||||
{
|
||||
d = Data::allocate(size + 1).first;
|
||||
Q_CHECK_PTR(d);
|
||||
d->size = size;
|
||||
d->data()[size] = '\0';
|
||||
QPair<Data *, ushort *> pair = Data::allocate(size + 1);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = size;
|
||||
Q_CHECK_PTR(d.d);
|
||||
d.b[size] = '\0';
|
||||
}
|
||||
|
||||
/*! \fn QString::QString(QLatin1String str)
|
||||
@ -2169,11 +2183,13 @@ QString::QString(int size, Qt::Initialization)
|
||||
*/
|
||||
QString::QString(QChar ch)
|
||||
{
|
||||
d = Data::allocate(2).first;
|
||||
Q_CHECK_PTR(d);
|
||||
d->size = 1;
|
||||
d->data()[0] = ch.unicode();
|
||||
d->data()[1] = '\0';
|
||||
QPair<Data *, ushort *> pair = Data::allocate(2);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = 1;
|
||||
Q_CHECK_PTR(d.d);
|
||||
d.b[0] = ch.unicode();
|
||||
d.b[1] = '\0';
|
||||
}
|
||||
|
||||
/*! \fn QString::QString(const QByteArray &ba)
|
||||
@ -2195,7 +2211,7 @@ QString::QString(QChar ch)
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*! \fn QString::QString(QStringDataPtr)
|
||||
/*! \fn QString::QString(QStringPrivate)
|
||||
\internal
|
||||
*/
|
||||
|
||||
@ -2265,16 +2281,16 @@ void QString::resize(int size)
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
|
||||
if (!d->isShared() && !d->isMutable() && size < d->size) {
|
||||
d->size = size;
|
||||
if (!d.d->isShared() && !d.d->isMutable() && size < int(d.size)) {
|
||||
d.size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->needsDetach() || size > capacity())
|
||||
if (d.d->needsDetach() || size > capacity())
|
||||
reallocData(uint(size) + 1u, true);
|
||||
if (d->isMutable()) {
|
||||
d->size = size;
|
||||
d->data()[size] = '\0';
|
||||
if (d.d->isMutable()) {
|
||||
d.size = size;
|
||||
d.b[size] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@ -2294,7 +2310,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.b + oldSize, difference, fillChar.unicode());
|
||||
}
|
||||
|
||||
/*! \fn int QString::capacity() const
|
||||
@ -2349,30 +2365,33 @@ void QString::resize(int size, QChar fillChar)
|
||||
|
||||
void QString::reallocData(uint alloc, bool grow)
|
||||
{
|
||||
auto allocOptions = d->detachFlags();
|
||||
auto allocOptions = d.d->detachFlags();
|
||||
if (grow)
|
||||
allocOptions |= QArrayData::GrowsForward;
|
||||
|
||||
if (d->needsDetach()) {
|
||||
Data *x = Data::allocate(alloc, allocOptions).first;
|
||||
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->deref())
|
||||
Data::deallocate(d);
|
||||
d = x;
|
||||
if (d.d->needsDetach()) {
|
||||
QPair<Data *, ushort *> pair = Data::allocate(alloc, allocOptions);
|
||||
Q_CHECK_PTR(pair.first);
|
||||
d.size = qMin(alloc - 1, d.size);
|
||||
::memcpy(pair.second, d.b, d.size * sizeof(QChar));
|
||||
pair.second[d.size] = 0;
|
||||
if (!d.d->deref())
|
||||
Data::deallocate(d.d);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
} else {
|
||||
Data *p = Data::reallocateUnaligned(d, d->data(), alloc, allocOptions).first;
|
||||
Q_CHECK_PTR(p);
|
||||
d = p;
|
||||
QPair<Data *, ushort *> pair =
|
||||
Data::reallocateUnaligned(static_cast<Data *>(d.d), d.b, alloc, allocOptions);
|
||||
Q_CHECK_PTR(pair.first);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
@ -2391,9 +2410,9 @@ void QString::expand(int i)
|
||||
|
||||
QString &QString::operator=(const QString &other) noexcept
|
||||
{
|
||||
other.d->ref();
|
||||
if (!d->deref())
|
||||
Data::deallocate(d);
|
||||
other.d.d->ref();
|
||||
if (!d.d->deref())
|
||||
Data::deallocate(d.d);
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
@ -2415,9 +2434,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.b[other.size()] = 0;
|
||||
qt_from_latin1(d.b, other.latin1(), other.size());
|
||||
} else {
|
||||
*this = fromLatin1(other.latin1(), other.size());
|
||||
}
|
||||
@ -2480,10 +2499,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.b[0] = ch.unicode();
|
||||
d.b[1] = 0;
|
||||
d.size = 1;
|
||||
} else {
|
||||
operator=(QString(ch));
|
||||
}
|
||||
@ -2569,13 +2587,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.b + i + len, d.b + i, (d.size - i - len) * sizeof(QChar));
|
||||
qt_from_latin1(d.b + i, s, uint(len));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -2592,7 +2610,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->size) {
|
||||
if (s >= d.b && s < d.b + d.size) {
|
||||
// Part of me - take a copy
|
||||
ushort *tmp = static_cast<ushort *>(::malloc(size * sizeof(QChar)));
|
||||
Q_CHECK_PTR(tmp);
|
||||
@ -2602,13 +2620,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.b + i + size, d.b + i, (d.size - i - size) * sizeof(QChar));
|
||||
memcpy(d.b + i, s, size * sizeof(QChar));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -2622,15 +2640,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.b + i + 1, d.b + i, (d.size - i - 1) * sizeof(QChar));
|
||||
d.b[i] = ch.unicode();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -2654,15 +2672,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->needsDetach() || d->size + str.d->size > capacity())
|
||||
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.d->needsDetach() || size() + str.size() > capacity())
|
||||
reallocData(uint(size() + str.size()) + 1u, true);
|
||||
memcpy(d.b + d.size, str.d.b, str.d.size * sizeof(QChar));
|
||||
d.size += str.d.size;
|
||||
d.b[d.size] = '\0';
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
@ -2677,11 +2695,11 @@ QString &QString::append(const QString &str)
|
||||
QString &QString::append(const QChar *str, int len)
|
||||
{
|
||||
if (str && len > 0) {
|
||||
if (d->needsDetach() || uint(d->size + len) + 1u > d->allocatedCapacity())
|
||||
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.d->needsDetach() || size() + len > capacity())
|
||||
reallocData(uint(size() + len) + 1u, true);
|
||||
memcpy(d.b + d.size, str, len * sizeof(QChar));
|
||||
d.size += len;
|
||||
d.b[d.size] = '\0';
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -2696,12 +2714,12 @@ QString &QString::append(QLatin1String str)
|
||||
const char *s = str.latin1();
|
||||
if (s) {
|
||||
int len = str.size();
|
||||
if (d->needsDetach() || d->size + len > capacity())
|
||||
reallocData(uint(d->size + len) + 1u, true);
|
||||
ushort *i = d->data() + d->size;
|
||||
if (d.d->needsDetach() || size() + len > capacity())
|
||||
reallocData(uint(size() + len) + 1u, true);
|
||||
ushort *i = d.b + d.size;
|
||||
qt_from_latin1(i, s, uint(len));
|
||||
i[len] = '\0';
|
||||
d->size += len;
|
||||
d.size += len;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -2743,10 +2761,10 @@ QString &QString::append(QLatin1String str)
|
||||
*/
|
||||
QString &QString::append(QChar ch)
|
||||
{
|
||||
if (d->needsDetach() || d->size + 1 > capacity())
|
||||
reallocData(uint(d->size) + 2u, true);
|
||||
d->data()[d->size++] = ch.unicode();
|
||||
d->data()[d->size] = '\0';
|
||||
if (d.d->needsDetach() || size() + 1 > capacity())
|
||||
reallocData(uint(d.size) + 2u, true);
|
||||
d.b[d.size++] = ch.unicode();
|
||||
d.b[d.size] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -2839,16 +2857,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.b + pos, d.b + pos + len,
|
||||
(d.size - pos - len + 1) * sizeof(ushort));
|
||||
d.size -= len;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -2993,10 +3011,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);
|
||||
@ -3060,10 +3078,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.b, d.size)) // Use copy in place of vulnerable original:
|
||||
after = afterBuffer = textCopy(after, alen);
|
||||
|
||||
QT_TRY {
|
||||
@ -3071,36 +3089,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.b + 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.b+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.b + to, d.b + movestart, msize * sizeof(QChar));
|
||||
to += msize;
|
||||
}
|
||||
if (alen) {
|
||||
memcpy(d->data() + to, after, alen * sizeof(QChar));
|
||||
memcpy(d.b + 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.b + to, d.b + 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) {
|
||||
@ -3108,9 +3126,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.b + moveto, d.b + movestart,
|
||||
(moveend - movestart)*sizeof(QChar));
|
||||
memcpy(d->data() + insertstart, after, alen * sizeof(QChar));
|
||||
memcpy(d.b + insertstart, after, alen * sizeof(QChar));
|
||||
moveend = movestart-blen;
|
||||
}
|
||||
}
|
||||
@ -3136,7 +3154,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 {
|
||||
@ -3171,10 +3189,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.b, d.size))
|
||||
after = afterBuffer = textCopy(after, alen);
|
||||
|
||||
if (!beforeBuffer && pointsIntoRange(before, d->data(), d->size)) {
|
||||
if (!beforeBuffer && pointsIntoRange(before, d.b, d.size)) {
|
||||
beforeBuffer = textCopy(before, blen);
|
||||
matcher = QStringMatcher(beforeBuffer, blen, cs);
|
||||
}
|
||||
@ -3203,13 +3221,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());
|
||||
@ -3219,14 +3237,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.b[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.b[index]) == cc)
|
||||
indices[pos++] = index;
|
||||
index++;
|
||||
}
|
||||
@ -3234,12 +3252,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;
|
||||
}
|
||||
@ -3254,13 +3272,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.b;
|
||||
ushort *const e = i + d.size;
|
||||
i += idx;
|
||||
*i = a;
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
@ -3321,7 +3339,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);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3341,7 +3359,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);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3377,7 +3395,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;
|
||||
@ -3390,7 +3408,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;
|
||||
@ -3936,7 +3954,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();
|
||||
@ -4035,8 +4053,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
|
||||
@ -4051,14 +4069,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.b + 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.b), 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.b + copystart), (d.size - copystart) * sizeof(QChar));
|
||||
newstring.resize(newlen);
|
||||
*this = newstring;
|
||||
caretMode = QRegExp::CaretWontMatch;
|
||||
@ -4098,7 +4116,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();
|
||||
|
||||
@ -4850,9 +4868,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.b, n);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4868,9 +4886,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);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4893,18 +4911,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).first };
|
||||
QPair<Data *, ushort *> pair = Data::allocate(0);
|
||||
QStringPrivate 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();
|
||||
@ -5151,7 +5170,7 @@ QByteArray QString::toLatin1_helper_inplace(QString &s)
|
||||
|
||||
// Swap the d pointers.
|
||||
// Kids, avert your eyes. Don't try this at home.
|
||||
QArrayData *ba_d = s.d;
|
||||
QArrayData *ba_d = s.d.d;
|
||||
|
||||
// multiply the allocated capacity by sizeof(ushort)
|
||||
ba_d->alloc *= sizeof(ushort);
|
||||
@ -5348,31 +5367,38 @@ QVector<uint> QtPrivate::convertToUcs4(QStringView string)
|
||||
return qt_convert_to_ucs4(string);
|
||||
}
|
||||
|
||||
QString::Data *QString::fromLatin1_helper(const char *str, int size)
|
||||
QStringPrivate QString::fromLatin1_helper(const char *str, int size)
|
||||
{
|
||||
Data *d;
|
||||
QStringPrivate d;
|
||||
if (!str) {
|
||||
d = Data::sharedNull();
|
||||
d.d = Data::sharedNull();
|
||||
d.b = Data::sharedNullData();
|
||||
d.size = 0;
|
||||
} else if (size == 0 || (!*str && size < 0)) {
|
||||
d = Data::allocate(0).first;
|
||||
QPair<Data *, ushort *> pair = Data::allocate(0);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = 0;
|
||||
} else {
|
||||
if (size < 0)
|
||||
size = qstrlen(str);
|
||||
d = Data::allocate(size + 1).first;
|
||||
Q_CHECK_PTR(d);
|
||||
d->size = size;
|
||||
d->data()[size] = '\0';
|
||||
ushort *dst = d->data();
|
||||
QPair<Data *, ushort *> pair = Data::allocate(size + 1);
|
||||
d.d = pair.first;
|
||||
d.b = pair.second;
|
||||
d.size = size;
|
||||
Q_CHECK_PTR(d.d);
|
||||
d.b[size] = '\0';
|
||||
ushort *dst = d.b;
|
||||
|
||||
qt_from_latin1(dst, str, uint(size));
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
QString::Data *QString::fromAscii_helper(const char *str, int size)
|
||||
QStringPrivate QString::fromAscii_helper(const char *str, int size)
|
||||
{
|
||||
QString s = fromUtf8(str, size);
|
||||
s.d->ref();
|
||||
s.d.d->ref();
|
||||
return s.d;
|
||||
}
|
||||
|
||||
@ -5418,7 +5444,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).first };
|
||||
QPair<Data *, ushort *> pair = Data::allocate(0);
|
||||
QStringPrivate empty = { pair.first, pair.second, 0 };
|
||||
return QString(empty);
|
||||
}
|
||||
#if QT_CONFIG(textcodec)
|
||||
@ -5588,7 +5615,7 @@ QString& QString::setUnicode(const QChar *unicode, int size)
|
||||
{
|
||||
resize(size);
|
||||
if (unicode && size)
|
||||
memcpy(d->data(), unicode, size * sizeof(QChar));
|
||||
memcpy(d.b, unicode, size * sizeof(QChar));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -5821,7 +5848,7 @@ QString QString::trimmed_helper(QString &str)
|
||||
|
||||
void QString::truncate(int pos)
|
||||
{
|
||||
if (pos < d->size)
|
||||
if (pos < size())
|
||||
resize(pos);
|
||||
}
|
||||
|
||||
@ -5843,7 +5870,7 @@ void QString::truncate(int pos)
|
||||
void QString::chop(int n)
|
||||
{
|
||||
if (n > 0)
|
||||
resize(d->size - n);
|
||||
resize(d.size - n);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -5860,10 +5887,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.b + d.size;
|
||||
QChar *b = (QChar*)d.b;
|
||||
while (i != b)
|
||||
*--i = ch;
|
||||
}
|
||||
@ -6444,11 +6471,11 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
|
||||
|
||||
const ushort *QString::utf16() const
|
||||
{
|
||||
if (!d->isMutable()) {
|
||||
if (!d.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.b;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -6477,8 +6504,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.b, d.b, sizeof(QChar)*len);
|
||||
QChar *uc = (QChar*)result.d.b + len;
|
||||
while (padlen--)
|
||||
* uc++ = fill;
|
||||
} else {
|
||||
@ -6515,11 +6542,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.b;
|
||||
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.b), sizeof(QChar)*len);
|
||||
} else {
|
||||
if (truncate)
|
||||
result = left(width);
|
||||
@ -7928,7 +7955,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) {
|
||||
@ -7937,27 +7964,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.capacity() != resultSize)
|
||||
return QString(); // not enough memory
|
||||
|
||||
memcpy(result.d->data(), d->data(), d->size * sizeof(ushort));
|
||||
memcpy(result.d.b, d.b, d.size * sizeof(ushort));
|
||||
|
||||
int sizeSoFar = d->size;
|
||||
ushort *end = result.d->data() + sizeSoFar;
|
||||
int sizeSoFar = d.size;
|
||||
ushort *end = result.d.b + sizeSoFar;
|
||||
|
||||
const int halfResultSize = resultSize >> 1;
|
||||
while (sizeSoFar <= halfResultSize) {
|
||||
memcpy(end, result.d->data(), sizeSoFar * sizeof(ushort));
|
||||
memcpy(end, result.d.b, 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.b, (resultSize - sizeSoFar) * sizeof(ushort));
|
||||
result.d.b[resultSize] = '\0';
|
||||
result.d.size = resultSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -8957,8 +8984,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.b;
|
||||
const ushort * const end = p + d.size;
|
||||
while (p < end) {
|
||||
ushort uc = *p;
|
||||
// sort out regions of complex text formatting
|
||||
@ -9107,17 +9134,21 @@ bool QString::isRightToLeft() const
|
||||
*/
|
||||
QString QString::fromRawData(const QChar *unicode, int size)
|
||||
{
|
||||
Data *x;
|
||||
QStringPrivate x;
|
||||
x.size = size;
|
||||
if (!unicode) {
|
||||
x = Data::sharedNull();
|
||||
x.d = Data::sharedNull();
|
||||
x.b = Data::sharedNullData();
|
||||
} else if (!size) {
|
||||
x = Data::allocate(0).first;
|
||||
QPair<Data *, ushort *> pair = Data::allocate(0);
|
||||
x.d = pair.first;
|
||||
x.b = pair.second;
|
||||
} else {
|
||||
x = Data::fromRawData(reinterpret_cast<const ushort *>(unicode), size).ptr;
|
||||
Q_CHECK_PTR(x);
|
||||
x.b = const_cast<ushort *>(reinterpret_cast<const ushort *>(unicode));
|
||||
x.d = Data::fromRawData(x.b, size).ptr;
|
||||
Q_CHECK_PTR(x.d);
|
||||
}
|
||||
QStringDataPtr dataPtr = { x };
|
||||
return QString(dataPtr);
|
||||
return QString(x);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -9138,11 +9169,11 @@ QString &QString::setRawData(const QChar *unicode, int size)
|
||||
{
|
||||
if (!unicode || !size) {
|
||||
clear();
|
||||
} else if (d->isShared() || !IS_RAW_DATA(d)) {
|
||||
} else if (d.d->isShared() || !IS_RAW_DATA(d)) {
|
||||
*this = fromRawData(unicode, size);
|
||||
} else {
|
||||
d->size = size;
|
||||
d->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(d);
|
||||
d.size = size;
|
||||
d.b = const_cast<ushort *>(reinterpret_cast<const ushort *>(unicode));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
#include <QtCore/qchar.h>
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qrefcount.h>
|
||||
#include <QtCore/qarraydata.h>
|
||||
#include <QtCore/qnamespace.h>
|
||||
#include <QtCore/qstringliteral.h>
|
||||
#include <QtCore/qstringalgorithms.h>
|
||||
@ -246,9 +246,8 @@ qsizetype QStringView::lastIndexOf(QLatin1String s, qsizetype from, Qt::CaseSens
|
||||
|
||||
class Q_CORE_EXPORT QString
|
||||
{
|
||||
typedef QTypedArrayData<ushort> Data;
|
||||
public:
|
||||
typedef QStringData Data;
|
||||
|
||||
inline QString() noexcept;
|
||||
explicit QString(const QChar *unicode, int size = -1);
|
||||
QString(QChar c);
|
||||
@ -259,12 +258,13 @@ public:
|
||||
QString &operator=(QChar c);
|
||||
QString &operator=(const QString &) noexcept;
|
||||
QString &operator=(QLatin1String latin1);
|
||||
inline QString(QString && other) noexcept : d(other.d) { other.d = Data::sharedNull(); }
|
||||
inline QString(QString &&other) noexcept : d(std::move(other.d))
|
||||
{ other.d.d = Data::sharedNull(); other.d.b = Data::sharedNullData(); other.d.size = 0; }
|
||||
inline QString &operator=(QString &&other) noexcept
|
||||
{ qSwap(d, other.d); return *this; }
|
||||
inline void swap(QString &other) noexcept { qSwap(d, other.d); }
|
||||
inline int size() const { return d->size; }
|
||||
inline int count() const { return d->size; }
|
||||
inline int size() const { return d.size; }
|
||||
inline int count() const { return d.size; }
|
||||
inline int length() const;
|
||||
inline bool isEmpty() const;
|
||||
void resize(int size);
|
||||
@ -285,7 +285,7 @@ public:
|
||||
|
||||
inline void detach();
|
||||
inline bool isDetached() const;
|
||||
inline bool isSharedWith(const QString &other) const { return d == other.d; }
|
||||
inline bool isSharedWith(const QString &other) const { return d.d == other.d.d; }
|
||||
void clear();
|
||||
|
||||
inline const QChar at(int i) const;
|
||||
@ -540,10 +540,10 @@ public:
|
||||
inline QString &prepend(QLatin1String s) { return insert(0, s); }
|
||||
|
||||
inline QString &operator+=(QChar c) {
|
||||
if (d->needsDetach() || d->size + 1 > capacity())
|
||||
reallocData(uint(d->size) + 2u, true);
|
||||
d->data()[d->size++] = c.unicode();
|
||||
d->data()[d->size] = '\0';
|
||||
if (d.d->needsDetach() || int(d.size + 1) > capacity())
|
||||
reallocData(uint(d.size) + 2u, true);
|
||||
d.b[d.size++] = c.unicode();
|
||||
d.b[d.size] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -656,8 +656,7 @@ public:
|
||||
// note - this are all inline so we can benefit from strlen() compile time optimizations
|
||||
static inline QString fromLatin1(const char *str, int size = -1)
|
||||
{
|
||||
QStringDataPtr dataPtr = { fromLatin1_helper(str, (str && size == -1) ? int(strlen(str)) : size) };
|
||||
return QString(dataPtr);
|
||||
return QString(fromLatin1_helper(str, (str && size == -1) ? int(strlen(str)) : size));
|
||||
}
|
||||
static inline QString fromUtf8(const char *str, int size = -1)
|
||||
{
|
||||
@ -908,17 +907,17 @@ public:
|
||||
struct Null { };
|
||||
QT_DEPRECATED_X("use QString()")
|
||||
static const Null null;
|
||||
inline QString(const Null &): d(Data::sharedNull()) {}
|
||||
inline QString(const Null &) { d.d = Data::sharedNull(); d.b = Data::sharedNullData(); d.size = 0; }
|
||||
inline QString &operator=(const Null &) { *this = QString(); return *this; }
|
||||
#endif
|
||||
inline bool isNull() const { return d == Data::sharedNull(); }
|
||||
inline bool isNull() const { return d.d == Data::sharedNull(); }
|
||||
|
||||
|
||||
bool isSimpleText() const;
|
||||
bool isRightToLeft() const;
|
||||
|
||||
QString(int size, Qt::Initialization);
|
||||
Q_DECL_CONSTEXPR inline QString(QStringDataPtr dd) : d(dd.ptr) {}
|
||||
explicit QString(QStringPrivate dd) : d(dd) {}
|
||||
|
||||
private:
|
||||
#if defined(QT_NO_CAST_FROM_ASCII)
|
||||
@ -930,7 +929,7 @@ private:
|
||||
QString &operator=(const QByteArray &a);
|
||||
#endif
|
||||
|
||||
Data *d;
|
||||
QStringPrivate d;
|
||||
|
||||
friend inline bool operator==(QChar, const QString &) noexcept;
|
||||
friend inline bool operator< (QChar, const QString &) noexcept;
|
||||
@ -968,8 +967,8 @@ private:
|
||||
static QString trimmed_helper(QString &str);
|
||||
static QString simplified_helper(const QString &str);
|
||||
static QString simplified_helper(QString &str);
|
||||
static Data *fromLatin1_helper(const char *str, int size = -1);
|
||||
static Data *fromAscii_helper(const char *str, int size = -1);
|
||||
static QStringPrivate fromLatin1_helper(const char *str, int size = -1);
|
||||
static QStringPrivate fromAscii_helper(const char *str, int size = -1);
|
||||
static QString fromUtf8_helper(const char *str, int size);
|
||||
static QString fromLocal8Bit_helper(const char *, int size);
|
||||
static QByteArray toLatin1_helper(const QString &);
|
||||
@ -1005,7 +1004,7 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Data * DataPtr;
|
||||
typedef QStringPrivate DataPtr;
|
||||
inline DataPtr &data_ptr() { return d; }
|
||||
};
|
||||
|
||||
@ -1021,31 +1020,31 @@ QString QStringView::toString() const
|
||||
inline QString::QString(QLatin1String aLatin1) : d(fromLatin1_helper(aLatin1.latin1(), aLatin1.size()))
|
||||
{ }
|
||||
inline int QString::length() const
|
||||
{ return d->size; }
|
||||
{ return d.size; }
|
||||
inline const QChar QString::at(int i) const
|
||||
{ Q_ASSERT(uint(i) < uint(size())); return QChar(d->data()[i]); }
|
||||
{ Q_ASSERT(uint(i) < uint(size())); return QChar(d.b[i]); }
|
||||
inline const QChar QString::operator[](int i) const
|
||||
{ Q_ASSERT(uint(i) < uint(size())); return QChar(d->data()[i]); }
|
||||
{ Q_ASSERT(uint(i) < uint(size())); return QChar(d.b[i]); }
|
||||
inline bool QString::isEmpty() const
|
||||
{ return d->size == 0; }
|
||||
{ return d.size == 0; }
|
||||
inline const QChar *QString::unicode() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b); }
|
||||
inline const QChar *QString::data() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b); }
|
||||
inline QChar *QString::data()
|
||||
{ detach(); return reinterpret_cast<QChar*>(d->data()); }
|
||||
{ detach(); return reinterpret_cast<QChar*>(d.b); }
|
||||
inline const QChar *QString::constData() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b); }
|
||||
inline void QString::detach()
|
||||
{ if (d->needsDetach()) reallocData(uint(d->size) + 1u); }
|
||||
{ if (d.d->needsDetach()) reallocData(d.size + 1u); }
|
||||
inline bool QString::isDetached() const
|
||||
{ return !d->isShared(); }
|
||||
{ return !d.d->isShared(); }
|
||||
inline void QString::clear()
|
||||
{ if (!isNull()) *this = QString(); }
|
||||
inline QString::QString(const QString &other) noexcept : d(other.d)
|
||||
{ Q_ASSERT(&other != this); d->ref(); }
|
||||
{ Q_ASSERT(&other != this); d.d->ref(); }
|
||||
inline int QString::capacity() const
|
||||
{ int realCapacity = d->constAllocatedCapacity(); return realCapacity ? realCapacity - 1 : 0; }
|
||||
{ int realCapacity = d.d->constAllocatedCapacity(); return realCapacity ? realCapacity - 1 : 0; }
|
||||
inline QString &QString::setNum(short n, int base)
|
||||
{ return setNum(qlonglong(n), base); }
|
||||
inline QString &QString::setNum(ushort n, int base)
|
||||
@ -1150,8 +1149,8 @@ public:
|
||||
inline operator QChar() const
|
||||
{
|
||||
using namespace QtPrivate::DeprecatedRefClassBehavior;
|
||||
if (Q_LIKELY(i < s.d->size))
|
||||
return QChar(s.d->data()[i]);
|
||||
if (Q_LIKELY(i < s.size()))
|
||||
return QChar(s.constData()[i]);
|
||||
#ifdef QT_DEBUG
|
||||
warn(WarningType::OutOfRange, EmittingClass::QCharRef);
|
||||
#endif
|
||||
@ -1160,7 +1159,7 @@ public:
|
||||
inline QCharRef &operator=(QChar c)
|
||||
{
|
||||
using namespace QtPrivate::DeprecatedRefClassBehavior;
|
||||
if (Q_UNLIKELY(i >= s.d->size)) {
|
||||
if (Q_UNLIKELY(i >= s.size())) {
|
||||
#ifdef QT_DEBUG
|
||||
warn(WarningType::OutOfRange, EmittingClass::QCharRef);
|
||||
#endif
|
||||
@ -1172,7 +1171,7 @@ public:
|
||||
#endif
|
||||
s.detach();
|
||||
}
|
||||
s.d->data()[i] = c.unicode();
|
||||
s.d.b[i] = c.unicode();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1254,27 +1253,27 @@ inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); }
|
||||
inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); }
|
||||
|
||||
|
||||
inline QString::QString() noexcept : d(Data::sharedNull()) {}
|
||||
inline QString::~QString() { if (!d->deref()) Data::deallocate(d); }
|
||||
inline QString::QString() noexcept { d.d = Data::sharedNull(); d.b = Data::sharedNullData(); d.size = 0; }
|
||||
inline QString::~QString() { if (!d.d->deref()) Data::deallocate(d.d); }
|
||||
|
||||
inline void QString::reserve(int asize)
|
||||
{
|
||||
if (d->needsDetach() || asize >= capacity())
|
||||
if (d.d->needsDetach() || asize >= capacity())
|
||||
reallocData(qMax(asize, size()) + 1u);
|
||||
|
||||
// we're not shared anymore, for sure
|
||||
d->flags |= Data::CapacityReserved;
|
||||
d.d->flags |= Data::CapacityReserved;
|
||||
}
|
||||
|
||||
inline void QString::squeeze()
|
||||
{
|
||||
if ((d->flags & Data::CapacityReserved) == 0)
|
||||
if ((d.d->flags & Data::CapacityReserved) == 0)
|
||||
return;
|
||||
if (d->needsDetach() || d->size < capacity())
|
||||
reallocData(uint(d->size) + 1u);
|
||||
if (d.d->needsDetach() || int(d.size) < capacity())
|
||||
reallocData(uint(d.size) + 1u);
|
||||
|
||||
// we're not shared anymore, for sure
|
||||
d->flags &= ~Data::CapacityReserved;
|
||||
d.d->flags &= ~Data::CapacityReserved;
|
||||
}
|
||||
|
||||
inline QString &QString::setUtf16(const ushort *autf16, int asize)
|
||||
@ -1284,21 +1283,21 @@ inline QCharRef QString::operator[](int i)
|
||||
inline QCharRef QString::front() { return operator[](0); }
|
||||
inline QCharRef QString::back() { return operator[](size() - 1); }
|
||||
inline QString::iterator QString::begin()
|
||||
{ detach(); return reinterpret_cast<QChar*>(d->data()); }
|
||||
{ detach(); return reinterpret_cast<QChar*>(d.b); }
|
||||
inline QString::const_iterator QString::begin() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b); }
|
||||
inline QString::const_iterator QString::cbegin() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b); }
|
||||
inline QString::const_iterator QString::constBegin() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b); }
|
||||
inline QString::iterator QString::end()
|
||||
{ detach(); return reinterpret_cast<QChar*>(d->data() + d->size); }
|
||||
{ detach(); return reinterpret_cast<QChar*>(d.b + d.size); }
|
||||
inline QString::const_iterator QString::end() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b + d.size); }
|
||||
inline QString::const_iterator QString::cend() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b + d.size); }
|
||||
inline QString::const_iterator QString::constEnd() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
|
||||
{ return reinterpret_cast<const QChar*>(d.b + d.size); }
|
||||
#if QT_STRINGVIEW_LEVEL < 2
|
||||
inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
|
||||
{ return indexOf(s, 0, cs) != -1; }
|
||||
@ -1525,7 +1524,8 @@ inline QString QString::fromStdU32String(const std::u32string &s)
|
||||
inline std::u32string QString::toStdU32String() const
|
||||
{
|
||||
std::u32string u32str(length(), char32_t(0));
|
||||
int len = toUcs4_helper(d->data(), length(), reinterpret_cast<uint*>(&u32str[0]));
|
||||
int len = toUcs4_helper(reinterpret_cast<const ushort *>(constData()), length(),
|
||||
reinterpret_cast<uint*>(&u32str[0]));
|
||||
u32str.resize(len);
|
||||
return u32str;
|
||||
}
|
||||
@ -1657,7 +1657,7 @@ public:
|
||||
inline const QChar *unicode() const
|
||||
{
|
||||
if (!m_string)
|
||||
return reinterpret_cast<const QChar *>(QString::Data::sharedNull()->data());
|
||||
return reinterpret_cast<const QChar *>(QString::Data::sharedNullData());
|
||||
return m_string->unicode() + m_position;
|
||||
}
|
||||
inline const QChar *data() const { return unicode(); }
|
||||
|
@ -49,8 +49,6 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
typedef QTypedArrayData<ushort> QStringData;
|
||||
|
||||
// all our supported compilers support Unicode string literals,
|
||||
// even if their Q_COMPILER_UNICODE_STRING has been revoked due
|
||||
// to lacking stdlib support. But QStringLiteral only needs the
|
||||
@ -65,43 +63,27 @@ Q_STATIC_ASSERT_X(sizeof(qunicodechar) == 2,
|
||||
#define QStringLiteral(str) \
|
||||
([]() noexcept -> QString { \
|
||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||
static const QStaticStringData<Size> qstring_literal = { \
|
||||
Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
|
||||
QT_UNICODE_LITERAL(str) }; \
|
||||
QStringDataPtr holder = { qstring_literal.data_ptr() }; \
|
||||
const QString qstring_literal_temp(holder); \
|
||||
return qstring_literal_temp; \
|
||||
static const QArrayData qstring_literal = { \
|
||||
Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, Size, 0, sizeof(QArrayData) \
|
||||
}; \
|
||||
QStringPrivate holder = { \
|
||||
const_cast<QArrayData *>(&qstring_literal), \
|
||||
reinterpret_cast<ushort *>(const_cast<qunicodechar *>(QT_UNICODE_LITERAL(str))), \
|
||||
Size \
|
||||
}; \
|
||||
return QString(holder); \
|
||||
}()) \
|
||||
/**/
|
||||
|
||||
#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
|
||||
{ Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, size, 0, offset } \
|
||||
/**/
|
||||
|
||||
#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER(size) \
|
||||
Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, sizeof(QStringData)) \
|
||||
/**/
|
||||
|
||||
#if QT_DEPRECATED_SINCE(5, 14)
|
||||
# define QStringViewLiteral(str) QStringView(QT_UNICODE_LITERAL(str), QtPrivate::Deprecated)
|
||||
#endif
|
||||
|
||||
template <int N>
|
||||
struct QStaticStringData
|
||||
struct QStringPrivate
|
||||
{
|
||||
QArrayData str;
|
||||
qunicodechar data[N + 1];
|
||||
|
||||
QStringData *data_ptr() const
|
||||
{
|
||||
Q_ASSERT(str.isStatic());
|
||||
return const_cast<QStringData *>(static_cast<const QStringData*>(&str));
|
||||
}
|
||||
};
|
||||
|
||||
struct QStringDataPtr
|
||||
{
|
||||
QStringData *ptr;
|
||||
QArrayData *d;
|
||||
ushort *b;
|
||||
uint size;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -608,8 +608,7 @@ QString verifyZeroTermination(const QString &str)
|
||||
QString::DataPtr strDataPtr = const_cast<QString &>(str).data_ptr();
|
||||
|
||||
// Skip if isStatic() or fromRawData(), as those offer no guarantees
|
||||
if (strDataPtr->isStatic()
|
||||
|| strDataPtr->offset != QString().data_ptr()->offset)
|
||||
if (strDataPtr.d->isStatic() || !strDataPtr.d->isMutable())
|
||||
return str;
|
||||
|
||||
int strSize = str.size();
|
||||
@ -620,7 +619,7 @@ QString verifyZeroTermination(const QString &str)
|
||||
.arg(strTerminator.unicode(), 4, 16, QChar('0'));
|
||||
|
||||
// Skip mutating checks on shared strings
|
||||
if (strDataPtr->isShared())
|
||||
if (strDataPtr.d->isShared())
|
||||
return str;
|
||||
|
||||
const QChar *strData = str.constData();
|
||||
@ -4070,12 +4069,12 @@ void tst_QString::setRawData()
|
||||
QVERIFY(cstr == QString(ptr, 1));
|
||||
|
||||
// This actually tests the recycling of the shared data object
|
||||
QString::DataPtr csd = cstr.data_ptr();
|
||||
void *csd = cstr.data_ptr().d;
|
||||
cstr.setRawData(ptr2, 1);
|
||||
QVERIFY(cstr.isDetached());
|
||||
QVERIFY(cstr.constData() == ptr2);
|
||||
QVERIFY(cstr == QString(ptr2, 1));
|
||||
QVERIFY(cstr.data_ptr() == csd);
|
||||
QVERIFY(cstr.data_ptr().d == csd);
|
||||
|
||||
// This tests the discarding of the shared data object
|
||||
cstr = "foo";
|
||||
@ -4083,12 +4082,12 @@ void tst_QString::setRawData()
|
||||
QVERIFY(cstr.constData() != ptr2);
|
||||
|
||||
// Another test of the fallback
|
||||
csd = cstr.data_ptr();
|
||||
csd = cstr.data_ptr().d;
|
||||
cstr.setRawData(ptr2, 1);
|
||||
QVERIFY(cstr.isDetached());
|
||||
QVERIFY(cstr.constData() == ptr2);
|
||||
QVERIFY(cstr == QString(ptr2, 1));
|
||||
QVERIFY(cstr.data_ptr() != csd);
|
||||
QVERIFY(cstr.data_ptr().d != csd);
|
||||
}
|
||||
|
||||
void tst_QString::fromStdString()
|
||||
@ -6637,8 +6636,7 @@ void tst_QString::literals()
|
||||
|
||||
QVERIFY(str.length() == 4);
|
||||
QVERIFY(str == QLatin1String("abcd"));
|
||||
QVERIFY(str.data_ptr()->isStatic());
|
||||
QVERIFY(str.data_ptr()->offset == sizeof(QStringData));
|
||||
QVERIFY(str.data_ptr().d->isStatic());
|
||||
|
||||
const QChar *s = str.constData();
|
||||
QString str2 = str;
|
||||
|
@ -126,9 +126,9 @@ void tst_toolsupport::offsets_data()
|
||||
#ifdef Q_PROCESSOR_X86
|
||||
// x86 32-bit has weird alignment rules. Refer to QtPrivate::AlignOf in
|
||||
// qglobal.h for more details.
|
||||
data << 176 << 272;
|
||||
data << 184 << 288;
|
||||
#else
|
||||
data << 180 << 272;
|
||||
data << 188 << 288;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user