From 00fbc087dd54b31e97b1557766b037b00120c43f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 25 Jun 2012 17:41:51 +0200 Subject: Inline the size and data pointers in QByteArray Change-Id: I82feeb2c9bd2900f421fc0c8d78698b1e83db043 Reviewed-by: Simon Hausmann --- src/corelib/global/qt_pch.h | 2 +- src/corelib/kernel/qobjectdefs.h | 2 +- src/corelib/text/qbytearray.cpp | 496 +++++++++++++++++++------------------- src/corelib/text/qbytearray.h | 139 +++++------ src/corelib/text/qbytearraylist.h | 5 - src/corelib/text/qstring.cpp | 20 +- src/corelib/text/qstring.h | 10 +- src/corelib/tools/qarraydataops.h | 5 - 8 files changed, 329 insertions(+), 350 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qt_pch.h b/src/corelib/global/qt_pch.h index 1663d9392f..0dfd6c745f 100644 --- a/src/corelib/global/qt_pch.h +++ b/src/corelib/global/qt_pch.h @@ -67,7 +67,7 @@ #include #include #include -//#include /* All moc genereated code has this include */ +#include /* All moc genereated code has this include */ #include #include #include diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index c4b9979293..229c97236e 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE class QByteArray; struct QArrayData; -typedef QArrayData QByteArrayData; +struct QByteArrayData; class QString; diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 841c02f1e4..c13a6d3379 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -731,27 +731,25 @@ QByteArray qUncompress(const uchar* data, int nbytes) return invalidCompressedData(); } - QScopedPointer d(QByteArray::Data::allocate(expectedSize + 1).first); + QPair pair = QByteArray::Data::allocate(expectedSize + 1); + QScopedPointer d(pair.first); if (Q_UNLIKELY(d.data() == nullptr)) return invalidCompressedData(); - d->size = expectedSize; forever { ulong alloc = len; - int res = ::uncompress((uchar*)d->data(), &len, + int res = ::uncompress((uchar*)pair.second, &len, data+4, nbytes-4); switch (res) { - case Z_OK: + case Z_OK: { Q_ASSERT(len <= alloc); Q_UNUSED(alloc); - d->size = len; - d->data()[len] = 0; - { - QByteArrayDataPtr dataPtr = { d.take() }; - return QByteArray(dataPtr); - } + QByteArrayData dataPtr = { d.take(), pair.second, uint(len) }; + pair.second[len] = '\0'; + return QByteArray(dataPtr); + } case Z_MEM_ERROR: qWarning("qUncompress: Z_MEM_ERROR: Not enough memory"); @@ -764,12 +762,12 @@ QByteArray qUncompress(const uchar* data, int nbytes) return invalidCompressedData(); } else { // grow the block - char *dataPointer = d->data(); - QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), dataPointer, len + 1).first; - if (Q_UNLIKELY(p == nullptr)) + pair = QByteArray::Data::reallocateUnaligned(d.data(), pair.second, len + 1); + Q_CHECK_PTR(pair.first); + if (Q_UNLIKELY(pair.first == nullptr)) return invalidCompressedData(); d.take(); // don't free - d.reset(p); + d.reset(pair.first); } continue; @@ -1185,9 +1183,9 @@ QByteArray qUncompress(const uchar* data, int nbytes) */ QByteArray &QByteArray::operator=(const QByteArray & 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; } @@ -1201,25 +1199,28 @@ QByteArray &QByteArray::operator=(const QByteArray & other) noexcept QByteArray &QByteArray::operator=(const char *str) { - Data *x; - if (!str) { - x = Data::sharedNull(); - } else if (!*str) { - x = Data::allocate(0).first; + if (!str || !*str) { + QPair pair; + if (!str) { + pair = qMakePair(Data::sharedNull(), Data::sharedNullData()); + } else { + pair = Data::allocate(0); + pair.first->ref(); + } + if (!d.d->deref()) + Data::deallocate(d.d); + d.d = pair.first; + d.b = pair.second; + d.size = 0; } else { const int len = int(strlen(str)); - const int fullLen = len + 1; - if (d->needsDetach() || fullLen > int(d->allocatedCapacity()) - || (len < d->size && fullLen < int(d->allocatedCapacity() >> 1))) - reallocData(fullLen, d->detachFlags()); - x = d; - memcpy(x->data(), str, fullLen); // include null terminator - x->size = len; + const size_t fullLen = len + 1; + if (d.d->needsDetach() || fullLen > d.d->allocatedCapacity() + || (len < size() && fullLen < (d.d->allocatedCapacity() >> 1))) + reallocData(fullLen, d.d->detachFlags()); + memcpy(d.b, str, fullLen); // include null terminator + d.size = len; } - x->ref(); - if (!d->deref()) - Data::deallocate(d); - d = x; return *this; } @@ -1555,7 +1556,7 @@ QByteArray &QByteArray::operator=(const char *str) */ void QByteArray::truncate(int pos) { - if (pos < d->size) + if (pos < size()) resize(pos); } @@ -1575,7 +1576,7 @@ void QByteArray::truncate(int pos) void QByteArray::chop(int n) { if (n > 0) - resize(d->size - n); + resize(size() - n); } @@ -1679,19 +1680,19 @@ void QByteArray::chop(int n) QByteArray::QByteArray(const char *data, int size) { if (!data) { - d = Data::sharedNull(); + d.d = Data::sharedNull(); + d.b = Data::sharedNullData(); + d.size = 0; } else { if (size < 0) size = int(strlen(data)); - if (!size) { - d = Data::allocate(0).first; - } else { - d = Data::allocate(uint(size) + 1u).first; - Q_CHECK_PTR(d); - d->size = size; - memcpy(d->data(), data, size); - d->data()[size] = '\0'; - } + QPair pair = Data::allocate(uint(size) + 1u); + Q_CHECK_PTR(pair.first); + d.d = pair.first; + d.b = pair.second; + d.size = size; + memcpy(d.b, data, size); + d.b[size] = '\0'; } } @@ -1705,13 +1706,18 @@ QByteArray::QByteArray(const char *data, int size) QByteArray::QByteArray(int size, char ch) { if (size <= 0) { - d = Data::allocate(0).first; + QPair pair = Data::allocate(0); + d.d = pair.first; + d.b = pair.second; + d.size = 0; } else { - d = Data::allocate(uint(size) + 1u).first; - Q_CHECK_PTR(d); - d->size = size; - memset(d->data(), ch, size); - d->data()[size] = '\0'; + QPair pair = Data::allocate(uint(size) + 1u); + Q_CHECK_PTR(pair.first); + d.d = pair.first; + d.b = pair.second; + d.size = size; + memset(d.b, ch, size); + d.b[size] = '\0'; } } @@ -1723,10 +1729,12 @@ QByteArray::QByteArray(int size, char ch) QByteArray::QByteArray(int size, Qt::Initialization) { - d = Data::allocate(uint(size) + 1u).first; - Q_CHECK_PTR(d); - d->size = size; - d->data()[size] = '\0'; + QPair pair = Data::allocate(uint(size) + 1u); + Q_CHECK_PTR(pair.first); + d.d = pair.first; + d.b = pair.second; + d.size = size; + d.b[size] = '\0'; } /*! @@ -1746,31 +1754,26 @@ void QByteArray::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->size == 0 && d->isStatic()) { - // - // Optimize the idiom: - // QByteArray a; - // a.resize(sz); - // ... - // which is used in place of the Qt 3 idiom: - // QByteArray a(sz); - // - Data *x = Data::allocate(uint(size) + 1u).first; - Q_CHECK_PTR(x); - x->size = size; - x->data()[size] = '\0'; - d = x; + if (size == 0 && !(d.d->flags & Data::CapacityReserved)) { + QPair pair = Data::allocate(0); + if (!d.d->deref()) + Data::deallocate(d.d); + d.d = pair.first; + d.b = pair.second; + d.size = 0; } else { - if (d->needsDetach() || size > capacity()) - reallocData(uint(size) + 1u, d->detachFlags() | Data::GrowsForward); - if (d->isMutable()) { - d->size = size; - d->data()[size] = '\0'; + if (d.d->needsDetach() || size > capacity() + || (!(d.d->flags & Data::CapacityReserved) && size < int(d.size) + && size < (capacity() >> 1))) + reallocData(uint(size) + 1u, d.d->detachFlags() | Data::GrowsForward); + d.size = size; + if (d.d->isMutable()) { + d.b[size] = '\0'; } } } @@ -1788,33 +1791,36 @@ void QByteArray::resize(int size) QByteArray &QByteArray::fill(char ch, int size) { - resize(size < 0 ? d->size : size); - if (d->size) - memset(d->data(), ch, d->size); + resize(size < 0 ? this->size() : size); + if (this->size()) + memset(d.b, ch, this->size()); return *this; } void QByteArray::reallocData(uint alloc, Data::ArrayOptions options) { - if (d->needsDetach()) { - Data *x = Data::allocate(alloc, options).first; - Q_CHECK_PTR(x); - x->size = qMin(int(alloc) - 1, d->size); - ::memcpy(x->data(), d->data(), x->size); - x->data()[x->size] = '\0'; - if (!d->deref()) - Data::deallocate(d); - d = x; + if (d.d->needsDetach()) { + QPair pair = Data::allocate(alloc, options); + Q_CHECK_PTR(pair.first); + d.size = qMin(alloc - 1, d.size); + ::memcpy(pair.second, d.b, d.size); + pair.second[d.size] = 0; + if (!d.d->deref()) + Data::deallocate(d.d); + d.d = pair.first; + d.b = pair.second; } else { - Data *x = Data::reallocateUnaligned(d, d->data(), alloc, options).first; - Q_CHECK_PTR(x); - d = x; + QPair pair = + Data::reallocateUnaligned(static_cast(d.d), d.b, alloc, options); + Q_CHECK_PTR(pair.first); + d.d = pair.first; + d.b = pair.second; } } void QByteArray::expand(int i) { - resize(qMax(i + 1, d->size)); + resize(qMax(i + 1, size())); } /*! @@ -1829,7 +1835,7 @@ void QByteArray::expand(int i) QByteArray QByteArray::nulTerminated() const { // is this fromRawData? - if (!IS_RAW_DATA(d)) + if (!IS_RAW_DATA(d.d)) return *this; // no, then we're sure we're zero terminated QByteArray copy(*this); @@ -1860,9 +1866,9 @@ QByteArray QByteArray::nulTerminated() const QByteArray &QByteArray::prepend(const QByteArray &ba) { - if (d->size == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) { + if (size() == 0 && d.d->isStatic() && !IS_RAW_DATA(ba.d.d)) { *this = ba; - } else if (ba.d->size != 0) { + } else if (ba.size() != 0) { QByteArray tmp = *this; *this = ba; append(tmp); @@ -1891,12 +1897,12 @@ QByteArray &QByteArray::prepend(const char *str) QByteArray &QByteArray::prepend(const char *str, int len) { if (str) { - if (d->needsDetach() || d->size + len > capacity()) - reallocData(uint(d->size + len) + 1u, d->detachFlags() | Data::GrowsForward); - memmove(d->data()+len, d->data(), d->size); - memcpy(d->data(), str, len); - d->size += len; - d->data()[d->size] = '\0'; + if (d.d->needsDetach() || size() + len > capacity()) + reallocData(uint(size() + len) + 1u, d.d->detachFlags() | Data::GrowsForward); + memmove(d.b+len, d.b, d.size); + memcpy(d.b, str, len); + d.size += len; + d.b[d.size] = '\0'; } return *this; } @@ -1917,12 +1923,12 @@ QByteArray &QByteArray::prepend(const char *str, int len) QByteArray &QByteArray::prepend(char ch) { - if (d->needsDetach() || d->size + 1 > capacity()) - reallocData(uint(d->size) + 2u, d->detachFlags() | Data::GrowsForward); - memmove(d->data()+1, d->data(), d->size); - d->data()[0] = ch; - ++d->size; - d->data()[d->size] = '\0'; + if (d.d->needsDetach() || size() + 1 > capacity()) + reallocData(uint(size()) + 2u, d.d->detachFlags() | Data::GrowsForward); + memmove(d.b+1, d.b, d.size); + d.b[0] = ch; + ++d.size; + d.b[d.size] = '\0'; return *this; } @@ -1952,14 +1958,14 @@ QByteArray &QByteArray::prepend(char ch) QByteArray &QByteArray::append(const QByteArray &ba) { - if (d->size == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) { + if (size() == 0 && d.d->isStatic() && !IS_RAW_DATA(ba.d.d)) { *this = ba; - } else if (ba.d->size != 0) { - if (d->needsDetach() || d->size + ba.d->size > capacity()) - reallocData(uint(d->size + ba.d->size) + 1u, d->detachFlags() | Data::GrowsForward); - memcpy(d->data() + d->size, ba.d->data(), ba.d->size); - d->size += ba.d->size; - d->data()[d->size] = '\0'; + } else if (ba.size() != 0) { + if (d.d->needsDetach() || size() + ba.size() > capacity()) + reallocData(uint(size() + ba.size()) + 1u, d.d->detachFlags() | Data::GrowsForward); + memcpy(d.b + d.size, ba.data(), ba.size()); + d.size += ba.size(); + d.b[d.size] = '\0'; } return *this; } @@ -1987,10 +1993,10 @@ QByteArray& QByteArray::append(const char *str) { if (str) { const int len = int(strlen(str)); - if (d->needsDetach() || d->size + len > capacity()) - reallocData(uint(d->size + len) + 1u, d->detachFlags() | Data::GrowsForward); - memcpy(d->data() + d->size, str, len + 1); // include null terminator - d->size += len; + if (d.d->needsDetach() || size() + len > capacity()) + reallocData(uint(size() + len) + 1u, d.d->detachFlags() | Data::GrowsForward); + memcpy(d.b + d.size, str, len + 1); // include null terminator + d.size += len; } return *this; } @@ -2012,11 +2018,11 @@ QByteArray &QByteArray::append(const char *str, int len) if (len < 0) len = qstrlen(str); if (str && len) { - if (d->needsDetach() || d->size + len > capacity()) - reallocData(uint(d->size + len) + 1u, d->detachFlags() | Data::GrowsForward); - memcpy(d->data() + d->size, str, len); // include null terminator - d->size += len; - d->data()[d->size] = '\0'; + if (d.d->needsDetach() || size() + len > capacity()) + reallocData(uint(size() + len) + 1u, d.d->detachFlags() | Data::GrowsForward); + memcpy(d.b + d.size, str, len); + d.size += len; + d.b[d.size] = '\0'; } return *this; } @@ -2040,10 +2046,10 @@ QByteArray &QByteArray::append(const char *str, int len) QByteArray& QByteArray::append(char ch) { - if (d->needsDetach() || d->size + 1 > capacity()) - reallocData(uint(d->size) + 2u, d->detachFlags() | Data::GrowsForward); - d->data()[d->size++] = ch; - d->data()[d->size] = '\0'; + if (d.d->needsDetach() || size() + 1 > capacity()) + reallocData(uint(size()) + 2u, d.d->detachFlags() | Data::GrowsForward); + d.b[d.size++] = ch; + d.b[d.size] = '\0'; return *this; } @@ -2084,7 +2090,7 @@ static inline QByteArray &qbytearray_insert(QByteArray *ba, QByteArray &QByteArray::insert(int i, const QByteArray &ba) { QByteArray copy(ba); - return qbytearray_insert(this, i, copy.d->data(), copy.d->size); + return qbytearray_insert(this, i, copy.constData(), copy.size()); } /*! @@ -2166,7 +2172,7 @@ QByteArray &QByteArray::insert(int i, int count, char ch) int oldsize = size(); resize(qMax(i, oldsize) + count); - char *dst = d->data(); + char *dst = d.b; if (i > oldsize) ::memset(dst + oldsize, 0x20, i - oldsize); else if (i < oldsize) @@ -2191,14 +2197,14 @@ QByteArray &QByteArray::insert(int i, int count, char ch) QByteArray &QByteArray::remove(int pos, int len) { - if (len <= 0 || uint(pos) >= uint(d->size)) + if (len <= 0 || uint(pos) >= uint(size())) return *this; detach(); - if (len >= d->size - pos) { + if (len >= size() - pos) { resize(pos); } else { - memmove(d->data() + pos, d->data() + pos + len, d->size - pos - len); - resize(d->size - len); + memmove(d.b + pos, d.b + pos + len, size() - pos - len); + resize(size() - len); } return *this; } @@ -2215,9 +2221,9 @@ QByteArray &QByteArray::remove(int pos, int len) QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after) { - if (len == after.d->size && (pos + len <= d->size)) { + if (len == after.size() && (pos + len <= size())) { detach(); - memmove(d->data() + pos, after.d->data(), len*sizeof(char)); + memmove(d.b + pos, after.data(), len*sizeof(char)); return *this; } else { QByteArray copy(after); @@ -2252,9 +2258,9 @@ QByteArray &QByteArray::replace(int pos, int len, const char *after) */ QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen) { - if (len == alen && (pos + len <= d->size)) { + if (len == alen && (pos + len <= size())) { detach(); - memcpy(d->data() + pos, after, len*sizeof(char)); + memcpy(d.b + pos, after, len*sizeof(char)); return *this; } else { remove(pos, len); @@ -2277,14 +2283,7 @@ QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen) QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &after) { - if (isNull() || before.d == after.d) - return *this; - - QByteArray aft = after; - if (after.d == d) - aft.detach(); - - return replace(before.constData(), before.size(), aft.constData(), aft.size()); + return replace(before.constData(), before.size(), after.constData(), after.size()); } /*! @@ -2297,11 +2296,7 @@ QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &afte QByteArray &QByteArray::replace(const char *c, const QByteArray &after) { - QByteArray aft = after; - if (after.d == d) - aft.detach(); - - return replace(c, qstrlen(c), aft.constData(), aft.size()); + return replace(c, qstrlen(c), after.constData(), after.size()); } /*! @@ -2321,13 +2316,13 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after // protect against before or after being part of this const char *a = after; const char *b = before; - if (after >= d->data() && after < d->data() + d->size) { + if (after >= constBegin() && after < constEnd()) { char *copy = (char *)malloc(asize); Q_CHECK_PTR(copy); memcpy(copy, after, asize); a = copy; } - if (before >= d->data() && before < d->data() + d->size) { + if (before >= constBegin() && before < constEnd()) { char *copy = (char *)malloc(bsize); Q_CHECK_PTR(copy); memcpy(copy, before, bsize); @@ -2336,8 +2331,8 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after QByteArrayMatcher matcher(before, bsize); int index = 0; - int len = d->size; - char *d = data(); + int len = size(); + char *d = data(); // detaches if (bsize == asize) { if (bsize) { @@ -2404,7 +2399,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after resize(newlen); len = newlen; } - d = this->d->data(); + d = this->d.b; // data(), without the detach() check while(pos) { pos--; @@ -2476,8 +2471,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after QByteArray &QByteArray::replace(char before, const QByteArray &after) { char b[2] = { before, '\0' }; - QByteArray cb = fromRawData(b, 1); - return replace(cb, after); + return replace(b, 1, after.constData(), after.size()); } /*! \fn QByteArray &QByteArray::replace(char before, const QString &after) @@ -2511,9 +2505,9 @@ QByteArray &QByteArray::replace(char before, const QByteArray &after) QByteArray &QByteArray::replace(char before, char after) { - if (d->size) { + if (!isEmpty()) { char *i = data(); - char *e = i + d->size; + char *e = i + size(); for (; i != e; ++i) if (*i == before) * i = after; @@ -2554,7 +2548,7 @@ QList QByteArray::split(char sep) const */ QByteArray QByteArray::repeated(int times) const { - if (d->size == 0) + if (isEmpty()) return *this; if (times <= 1) { @@ -2563,27 +2557,27 @@ QByteArray QByteArray::repeated(int times) const return QByteArray(); } - const int resultSize = times * d->size; + const int resultSize = times * size(); QByteArray result; result.reserve(resultSize); if (result.capacity() != resultSize) return QByteArray(); // not enough memory - memcpy(result.d->data(), d->data(), d->size); + memcpy(result.d.b, data(), size()); - int sizeSoFar = d->size; - char *end = result.d->data() + sizeSoFar; + int sizeSoFar = size(); + char *end = result.d.b + sizeSoFar; const int halfResultSize = resultSize >> 1; while (sizeSoFar <= halfResultSize) { - memcpy(end, result.d->data(), sizeSoFar); + memcpy(end, result.d.b, sizeSoFar); end += sizeSoFar; sizeSoFar <<= 1; } - memcpy(end, result.d->data(), resultSize - sizeSoFar); - result.d->data()[resultSize] = '\0'; - result.d->size = resultSize; + memcpy(end, result.d.b, resultSize - sizeSoFar); + result.d.b[resultSize] = '\0'; + result.d.size = resultSize; return result; } @@ -2605,17 +2599,17 @@ QByteArray QByteArray::repeated(int times) const int QByteArray::indexOf(const QByteArray &ba, int from) const { - const int ol = ba.d->size; + const int ol = ba.size(); if (ol == 0) return from; if (ol == 1) - return indexOf(*ba.d->data(), from); + return indexOf(ba[0], from); - const int l = d->size; - if (from > d->size || ol + from > l) + const int l = size(); + if (from > l || ol + from > l) return -1; - return qFindByteArray(d->data(), d->size, from, ba.d->data(), ol); + return qFindByteArray(data(), size(), from, ba.data(), ol); } /*! \fn int QByteArray::indexOf(const QString &str, int from) const @@ -2649,13 +2643,13 @@ int QByteArray::indexOf(const char *c, int from) const if (ol == 1) return indexOf(*c, from); - const int l = d->size; - if (from > d->size || ol + from > l) + const int l = size(); + if (from > l || ol + from > l) return -1; if (ol == 0) return from; - return qFindByteArray(d->data(), d->size, from, c, ol); + return qFindByteArray(data(), size(), from, c, ol); } /*! @@ -2674,13 +2668,13 @@ int QByteArray::indexOf(const char *c, int from) const int QByteArray::indexOf(char ch, int from) const { if (from < 0) - from = qMax(from + d->size, 0); - if (from < d->size) { - const char *n = d->data() + from - 1; - const char *e = d->data() + d->size; + from = qMax(from + size(), 0); + if (from < size()) { + const char *n = data() + from - 1; + const char *e = end(); while (++n != e) if (*n == ch) - return n - d->data(); + return n - data(); } return -1; } @@ -2735,11 +2729,11 @@ static int lastIndexOfHelper(const char *haystack, int l, const char *needle, in int QByteArray::lastIndexOf(const QByteArray &ba, int from) const { - const int ol = ba.d->size; + const int ol = ba.size(); if (ol == 1) - return lastIndexOf(*ba.d->data(), from); + return lastIndexOf(ba[0], from); - return lastIndexOfHelper(d->data(), d->size, ba.d->data(), ol, from); + return lastIndexOfHelper(data(), size(), ba.data(), ol, from); } /*! \fn int QByteArray::lastIndexOf(const QString &str, int from) const @@ -2774,7 +2768,7 @@ int QByteArray::lastIndexOf(const char *str, int from) const if (ol == 1) return lastIndexOf(*str, from); - return lastIndexOfHelper(d->data(), d->size, str, ol, from); + return lastIndexOfHelper(data(), size(), str, ol, from); } /*! @@ -2794,12 +2788,12 @@ int QByteArray::lastIndexOf(const char *str, int from) const int QByteArray::lastIndexOf(char ch, int from) const { if (from < 0) - from += d->size; - else if (from > d->size) - from = d->size-1; + from += size(); + else if (from > size()) + from = size()-1; if (from >= 0) { - const char *b = d->data(); - const char *n = d->data() + from + 1; + const char *b = data(); + const char *n = b + from + 1; while (n-- != b) if (*n == ch) return n - b; @@ -2818,7 +2812,7 @@ int QByteArray::count(const QByteArray &ba) const { int num = 0; int i = -1; - if (d->size > 500 && ba.d->size > 5) { + if (size() > 500 && ba.size() > 5) { QByteArrayMatcher matcher(ba); while ((i = matcher.indexIn(*this, i + 1)) != -1) ++num; @@ -2853,8 +2847,8 @@ int QByteArray::count(const char *str) const int QByteArray::count(char ch) const { int num = 0; - const char *i = d->data() + d->size; - const char *b = d->data(); + const char *i = end(); + const char *b = begin(); while (i != b) if (*--i == ch) ++num; @@ -2904,11 +2898,11 @@ int QByteArray::count(char ch) const */ bool QByteArray::startsWith(const QByteArray &ba) const { - if (d == ba.d || ba.d->size == 0) - return true; - if (d->size < ba.d->size) + if (size() < ba.size()) return false; - return memcmp(d->data(), ba.d->data(), ba.d->size) == 0; + if (data() == ba.data() || ba.size() == 0) + return true; + return memcmp(data(), ba.data(), ba.size()) == 0; } /*! \overload @@ -2921,9 +2915,9 @@ bool QByteArray::startsWith(const char *str) const if (!str || !*str) return true; const int len = int(strlen(str)); - if (d->size < len) + if (size() < len) return false; - return qstrncmp(d->data(), str, len) == 0; + return qstrncmp(data(), str, len) == 0; } /*! \overload @@ -2933,9 +2927,9 @@ bool QByteArray::startsWith(const char *str) const */ bool QByteArray::startsWith(char ch) const { - if (d->size == 0) + if (size() == 0) return false; - return d->data()[0] == ch; + return data()[0] == ch; } /*! @@ -2949,11 +2943,11 @@ bool QByteArray::startsWith(char ch) const */ bool QByteArray::endsWith(const QByteArray &ba) const { - if (d == ba.d || ba.d->size == 0) - return true; - if (d->size < ba.d->size) + if (size() < ba.size()) return false; - return memcmp(d->data() + d->size - ba.d->size, ba.d->data(), ba.d->size) == 0; + if (end() == ba.end() || ba.size() == 0) + return true; + return memcmp(end() - ba.size(), ba.data(), ba.size()) == 0; } /*! \overload @@ -2966,9 +2960,9 @@ bool QByteArray::endsWith(const char *str) const if (!str || !*str) return true; const int len = int(strlen(str)); - if (d->size < len) + if (size() < len) return false; - return qstrncmp(d->data() + d->size - len, str, len) == 0; + return qstrncmp(end() - len, str, len) == 0; } /* @@ -3050,9 +3044,9 @@ bool QByteArray::isLower() const */ bool QByteArray::endsWith(char ch) const { - if (d->size == 0) + if (size() == 0) return false; - return d->data()[d->size - 1] == ch; + return data()[size() - 1] == ch; } /*! @@ -3070,11 +3064,11 @@ bool QByteArray::endsWith(char ch) const QByteArray QByteArray::left(int len) const { - if (len >= d->size) + if (len >= size()) return *this; if (len < 0) len = 0; - return QByteArray(d->data(), len); + return QByteArray(data(), len); } /*! @@ -3092,11 +3086,11 @@ QByteArray QByteArray::left(int len) const QByteArray QByteArray::right(int len) const { - if (len >= d->size) + if (len >= size()) return *this; if (len < 0) len = 0; - return QByteArray(d->data() + d->size - len, len); + return QByteArray(end() - len, len); } /*! @@ -3121,13 +3115,14 @@ QByteArray QByteArray::mid(int pos, int len) const return QByteArray(); case QContainerImplHelper::Empty: { - QByteArrayDataPtr empty = { Data::allocate(0).first }; + auto alloc = Data::allocate(0); + QByteArrayData empty = { alloc.first, alloc.second, 0 }; return QByteArray(empty); } case QContainerImplHelper::Full: return *this; case QContainerImplHelper::Subset: - return QByteArray(d->data() + pos, len); + return QByteArray(d.b + pos, len); } Q_UNREACHABLE(); return QByteArray(); @@ -3230,9 +3225,11 @@ QByteArray QByteArray::toUpper_helper(QByteArray &a) void QByteArray::clear() { - if (!d->deref()) - Data::deallocate(d); - d = Data::sharedNull(); + if (!d.d->deref()) + Data::deallocate(d.d); + d.d = Data::sharedNull(); + d.b = Data::sharedNullData(); + d.size = 0; } #if !defined(QT_NO_DATASTREAM) || (defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE)) @@ -3709,13 +3706,13 @@ QByteArray QByteArray::trimmed_helper(QByteArray &a) QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const { QByteArray result; - int len = d->size; + int len = size(); int padlen = width - len; if (padlen > 0) { result.resize(len+padlen); if (len) - memcpy(result.d->data(), d->data(), len); - memset(result.d->data()+len, fill, padlen); + memcpy(result.d.b, data(), len); + memset(result.d.b+len, fill, padlen); } else { if (truncate) result = left(width); @@ -3746,13 +3743,13 @@ QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const { QByteArray result; - int len = d->size; + int len = size(); int padlen = width - len; if (padlen > 0) { result.resize(len+padlen); if (len) - memcpy(result.d->data()+padlen, data(), len); - memset(result.d->data(), fill, padlen); + memcpy(result.d.b+padlen, data(), len); + memset(result.d.b, fill, padlen); } else { if (truncate) result = left(width); @@ -3762,7 +3759,10 @@ QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const return result; } -bool QByteArray::isNull() const { return d == QArrayData::sharedNull(); } +bool QByteArray::isNull() const +{ + return d.d == QArrayData::sharedNull(); +} static qlonglong toIntegral_helper(const char *data, bool *ok, int base, qlonglong) { @@ -4089,19 +4089,19 @@ QByteArray QByteArray::toBase64(Base64Options options) const const char padchar = '='; int padlen = 0; - QByteArray tmp((d->size + 2) / 3 * 4, Qt::Uninitialized); + QByteArray tmp((size() + 2) / 3 * 4, Qt::Uninitialized); int i = 0; char *out = tmp.data(); - while (i < d->size) { + while (i < size()) { // encode 3 bytes at a time int chunk = 0; - chunk |= int(uchar(d->data()[i++])) << 16; - if (i == d->size) { + chunk |= int(uchar(data()[i++])) << 16; + if (i == size()) { padlen = 2; } else { - chunk |= int(uchar(d->data()[i++])) << 8; - if (i == d->size) + chunk |= int(uchar(data()[i++])) << 8; + if (i == size()) padlen = 1; else chunk |= int(uchar(data()[i++])); @@ -4431,17 +4431,23 @@ QByteArray QByteArray::number(double n, char f, int prec) QByteArray QByteArray::fromRawData(const char *data, int size) { - Data *x; + QByteArrayData x; if (!data) { - x = Data::sharedNull(); + x.d = Data::sharedNull(); + x.b = Data::sharedNullData(); + x.size = 0; } else if (!size) { - x = Data::allocate(0).first; + QPair pair = Data::allocate(0); + x.d = pair.first; + x.b = pair.second; + x.size = 0; } else { - x = Data::fromRawData(data, size).ptr; - Q_CHECK_PTR(x); + x.d = Data::fromRawData(data, size).ptr; + Q_CHECK_PTR(x.d); + x.b = const_cast(data); + x.size = size; } - QByteArrayDataPtr dataPtr = { x }; - return QByteArray(dataPtr); + return QByteArray(x); } /*! @@ -4462,11 +4468,11 @@ QByteArray &QByteArray::setRawData(const char *data, uint size) { if (!data || !size) { clear(); - } else if (d->isShared() || (d->flags & Data::RawDataType) == 0) { + } else if (d.d->isShared() || (d.d->flags & Data::RawDataType) == 0) { *this = fromRawData(data, size); } else { - d->size = size; - d->offset = data - reinterpret_cast(d); + d.size = size; + d.b = const_cast(data); } return *this; } @@ -4579,14 +4585,14 @@ QByteArray QByteArray::fromHex(const QByteArray &hexEncoded) */ QByteArray QByteArray::toHex(char separator) const { - if (!d->size) + if (isEmpty()) return QByteArray(); - const int length = separator ? (d->size * 3 - 1) : (d->size * 2); + const int length = separator ? (size() * 3 - 1) : (size() * 2); QByteArray hex(length, Qt::Uninitialized); char *hexData = hex.data(); - const uchar *data = (const uchar *)d->data(); - for (int i = 0, o = 0; i < d->size; ++i) { + const uchar *data = (const uchar *)this->data(); + for (int i = 0, o = 0; i < size(); ++i) { hexData[o++] = QtMiscUtils::toHexLower(data[i] >> 4); hexData[o++] = QtMiscUtils::toHexLower(data[i] & 0xf); diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h index 67a7e5da3d..f97f64f556 100644 --- a/src/corelib/text/qbytearray.h +++ b/src/corelib/text/qbytearray.h @@ -114,40 +114,22 @@ class QByteRef; class QString; class QDataStream; -typedef QArrayData QByteArrayData; - -template struct QStaticByteArrayData -{ - QByteArrayData ba; - char data[N + 1]; - - QByteArrayData *data_ptr() const - { - Q_ASSERT(ba.isStatic()); - return const_cast(&ba); - } -}; - -struct QByteArrayDataPtr +struct QByteArrayData { - QByteArrayData *ptr; + QArrayData *d; + char *b; + uint size; }; -#define Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \ - Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) - /**/ - -#define Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER(size) \ - Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, sizeof(QByteArrayData)) \ - /**/ - # define QByteArrayLiteral(str) \ ([]() -> QByteArray { \ enum { Size = sizeof(str) - 1 }; \ - static const QStaticByteArrayData qbytearray_literal = { \ - Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER(Size), \ - str }; \ - QByteArrayDataPtr holder = { qbytearray_literal.data_ptr() }; \ + static const QArrayData qbytearray_literal = { \ + Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, Size, 0, sizeof(QArrayData) }; \ + QByteArrayData holder = { \ + const_cast(&qbytearray_literal), \ + const_cast(str), \ + Size }; \ const QByteArray ba(holder); \ return ba; \ }()) \ @@ -177,10 +159,10 @@ public: QByteArray &operator=(const QByteArray &) noexcept; QByteArray &operator=(const char *str); - inline QByteArray(QByteArray && other) noexcept : d(other.d) { other.d = Data::sharedNull(); } + inline QByteArray(QByteArray && other) noexcept : d(std::move(other.d)) + { other.d.d = Data::sharedNull(); other.d.b = Data::sharedNullData(); other.d.size = 0; } inline QByteArray &operator=(QByteArray &&other) noexcept { qSwap(d, other.d); return *this; } - inline void swap(QByteArray &other) noexcept { qSwap(d, other.d); } @@ -203,7 +185,8 @@ public: inline const char *constData() const; inline void detach(); inline bool isDetached() const; - inline bool isSharedWith(const QByteArray &other) const { return d == other.d; } + inline bool isSharedWith(const QByteArray &other) const + { return data() == other.data() && size() == other.size(); } void clear(); inline char at(int i) const; @@ -431,18 +414,18 @@ public: static inline QByteArray fromStdString(const std::string &s); inline std::string toStdString() const; - inline int count() const { return d->size; } - int length() const { return d->size; } + inline int count() const { return int(d.size); } + int length() const { return int(d.size); } bool isNull() const; - inline QByteArray(QByteArrayDataPtr dd) - : d(static_cast(dd.ptr)) + explicit inline QByteArray(const QByteArrayData &dd) + : d(dd) { } private: operator QNoImplicitBoolCast() const; - Data *d; + QByteArrayData d; void reallocData(uint alloc, Data::ArrayOptions options); void expand(int i); QByteArray nulTerminated() const; @@ -460,63 +443,63 @@ private: friend class QString; friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes); public: - typedef Data * DataPtr; + typedef QByteArrayData DataPtr; inline DataPtr &data_ptr() { return d; } }; Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options) -inline QByteArray::QByteArray() noexcept : d(Data::sharedNull()) { } -inline QByteArray::~QByteArray() { if (!d->deref()) Data::deallocate(d); } +inline QByteArray::QByteArray() noexcept { d.d = Data::sharedNull(); d.b = Data::sharedNullData(); d.size = 0; } +inline QByteArray::~QByteArray() { if (!d.d->deref()) Data::deallocate(d.d); } inline int QByteArray::size() const -{ return d->size; } +{ return int(d.size); } inline char QByteArray::at(int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d.b[i]; } inline char QByteArray::operator[](int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d.b[i]; } inline bool QByteArray::isEmpty() const -{ return d->size == 0; } +{ return size() == 0; } #ifndef QT_NO_CAST_FROM_BYTEARRAY inline QByteArray::operator const char *() const -{ return d->data(); } +{ return data(); } inline QByteArray::operator const void *() const -{ return d->data(); } +{ return data(); } #endif inline char *QByteArray::data() -{ detach(); return d->data(); } +{ detach(); return d.b; } inline const char *QByteArray::data() const -{ return d->data(); } +{ return d.b; } inline const char *QByteArray::constData() const -{ return d->data(); } +{ return d.b; } inline void QByteArray::detach() -{ if (d->needsDetach()) reallocData(uint(d->size) + 1u, d->detachFlags()); } +{ if (d.d->needsDetach()) reallocData(uint(size()) + 1u, d.d->detachFlags()); } inline bool QByteArray::isDetached() const -{ return !d->isShared(); } +{ return !d.d->isShared(); } inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d) -{ d->ref(); } +{ d.d->ref(); } inline int QByteArray::capacity() const -{ int realCapacity = d->constAllocatedCapacity(); return realCapacity ? realCapacity - 1 : 0; } +{ int realCapacity = d.d->constAllocatedCapacity(); return realCapacity ? realCapacity - 1 : 0; } inline void QByteArray::reserve(int asize) { - if (d->needsDetach() || asize > capacity()) { - reallocData(qMax(uint(size()), uint(asize)) + 1u, d->detachFlags() | Data::CapacityReserved); + if (d.d->needsDetach() || asize > capacity()) { + reallocData(qMax(uint(size()), uint(asize)) + 1u, d.d->detachFlags() | Data::CapacityReserved); } else { - d->flags |= Data::CapacityReserved; + d.d->flags |= Data::CapacityReserved; } } inline void QByteArray::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, d->detachFlags() & ~Data::CapacityReserved); + if (d.d->needsDetach() || size() < capacity()) { + reallocData(uint(size()) + 1u, d.d->detachFlags() & ~Data::CapacityReserved); } else { - d->flags &= ~Data::CapacityReserved; + d.d->flags &= uint(~Data::CapacityReserved); } } @@ -550,8 +533,8 @@ public: inline operator char() const { using namespace QtPrivate::DeprecatedRefClassBehavior; - if (Q_LIKELY(i < a.d->size)) - return a.d->data()[i]; + if (Q_LIKELY(i < a.size())) + return a.constData()[i]; #ifdef QT_DEBUG warn(WarningType::OutOfRange, EmittingClass::QByteRef); #endif @@ -560,7 +543,7 @@ public: inline QByteRef &operator=(char c) { using namespace QtPrivate::DeprecatedRefClassBehavior; - if (Q_UNLIKELY(i >= a.d->size)) { + if (Q_UNLIKELY(i >= a.size())) { #ifdef QT_DEBUG warn(WarningType::OutOfRange, EmittingClass::QByteRef); #endif @@ -572,7 +555,7 @@ public: #endif a.detach(); } - a.d->data()[i] = c; + a.d.b[i] = c; return *this; } inline QByteRef &operator=(const QByteRef &c) @@ -580,17 +563,17 @@ public: return operator=(char(c)); } inline bool operator==(char c) const - { return a.d->data()[i] == c; } + { return a.data()[i] == c; } inline bool operator!=(char c) const - { return a.d->data()[i] != c; } + { return a.data()[i] != c; } inline bool operator>(char c) const - { return a.d->data()[i] > c; } + { return a.data()[i] > c; } inline bool operator>=(char c) const - { return a.d->data()[i] >= c; } + { return a.data()[i] >= c; } inline bool operator<(char c) const - { return a.d->data()[i] < c; } + { return a.data()[i] < c; } inline bool operator<=(char c) const - { return a.d->data()[i] <= c; } + { return a.data()[i] <= c; } }; inline QByteRef QByteArray::operator[](int i) @@ -598,23 +581,23 @@ inline QByteRef QByteArray::operator[](int i) inline QByteRef QByteArray::front() { return operator[](0); } inline QByteRef QByteArray::back() { return operator[](size() - 1); } inline QByteArray::iterator QByteArray::begin() -{ detach(); return d->data(); } +{ return data(); } inline QByteArray::const_iterator QByteArray::begin() const -{ return d->data(); } +{ return data(); } inline QByteArray::const_iterator QByteArray::cbegin() const -{ return d->data(); } +{ return data(); } inline QByteArray::const_iterator QByteArray::constBegin() const -{ return d->data(); } +{ return data(); } inline QByteArray::iterator QByteArray::end() -{ detach(); return d->data() + d->size; } +{ return data() + size(); } inline QByteArray::const_iterator QByteArray::end() const -{ return d->data() + d->size; } +{ return data() + size(); } inline QByteArray::const_iterator QByteArray::cend() const -{ return d->data() + d->size; } +{ return data() + size(); } inline QByteArray::const_iterator QByteArray::constEnd() const -{ return d->data() + d->size; } +{ return data() + size(); } inline QByteArray &QByteArray::append(int n, char ch) -{ return insert(d->size, n, ch); } +{ return insert(size(), n, ch); } inline QByteArray &QByteArray::prepend(int n, char ch) { return insert(0, n, ch); } inline QByteArray &QByteArray::operator+=(char c) diff --git a/src/corelib/text/qbytearraylist.h b/src/corelib/text/qbytearraylist.h index e113c6059c..d02fa6d20f 100644 --- a/src/corelib/text/qbytearraylist.h +++ b/src/corelib/text/qbytearraylist.h @@ -80,11 +80,6 @@ public: inline QByteArray join(char sep) const { return QtPrivate::QByteArrayList_join(self(), &sep, 1); } -#if 0 - inline int indexOf(const char *needle, int from = 0) const - { return QtPrivate::QByteArrayList_indexOf(self(), needle, from); } -#endif - private: typedef QVector Self; Self *self() { return static_cast(this); } diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index e1cd018351..7758687f0f 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -2288,8 +2288,8 @@ void QString::resize(int size) if (d.d->needsDetach() || size > capacity()) reallocData(uint(size) + 1u, true); + d.size = size; if (d.d->isMutable()) { - d.size = size; d.b[size] = '\0'; } } @@ -5170,24 +5170,24 @@ 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.d; + QByteArrayData ba_d = { + s.d.d, + reinterpret_cast(s.d.b), + length + }; // multiply the allocated capacity by sizeof(ushort) - ba_d->alloc *= sizeof(ushort); + ba_d.d->alloc *= sizeof(ushort); // reset ourselves to QString() s.d = QString().d; // do the in-place conversion - uchar *dst = reinterpret_cast(ba_d->data()); - qt_to_latin1(dst, data, length); - dst[length] = '\0'; - - QByteArrayDataPtr badptr = { ba_d }; - return QByteArray(badptr); + qt_to_latin1(reinterpret_cast(ba_d.b), data, length); + ba_d.b[length] = '\0'; + return QByteArray(ba_d); } - /*! \fn QByteArray QString::toLatin1() const diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index c2168af889..96c0ec7ceb 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -263,8 +263,8 @@ public: 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 int(d.size); } + inline int count() const { return int(d.size); } inline int length() const; inline bool isEmpty() const; void resize(int size); @@ -1020,7 +1020,7 @@ 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 int(d.size); } inline const QChar QString::at(int i) const { Q_ASSERT(uint(i) < uint(size())); return QChar(d.b[i]); } inline const QChar QString::operator[](int i) const @@ -1259,7 +1259,7 @@ inline QString::~QString() { if (!d.d->deref()) Data::deallocate(d.d); } inline void QString::reserve(int asize) { if (d.d->needsDetach() || asize >= capacity()) - reallocData(qMax(asize, size()) + 1u); + reallocData(uint(qMax(asize, size())) + 1u); // we're not shared anymore, for sure d.d->flags |= Data::CapacityReserved; @@ -1273,7 +1273,7 @@ inline void QString::squeeze() reallocData(uint(d.size) + 1u); // we're not shared anymore, for sure - d.d->flags &= ~Data::CapacityReserved; + d.d->flags &= uint(~Data::CapacityReserved); } inline QString &QString::setUtf16(const ushort *autf16, int asize) diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index f3de6b65a9..8ca181edf1 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -199,11 +199,6 @@ struct QPodArrayOps bool compare(const T *begin1, const T *begin2, size_t n) const { - // only use memcmp for fundamental types or pointers. - // Other types could have padding in the data structure or custom comparison - // operators that would break the comparison using memcmp - if (QArrayDataPointer::pass_parameter_by_value) - return ::memcmp(begin1, begin2, n * sizeof(T)) == 0; const T *end1 = begin1 + n; while (begin1 != end1) { if (*begin1 == *begin2) -- cgit v1.2.3