summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qmake/library/proitems.cpp3
-rw-r--r--qmake/library/proitems.h1
-rw-r--r--src/corelib/text/qbytearray.cpp40
-rw-r--r--src/corelib/text/qbytearray.h46
-rw-r--r--src/corelib/text/qstring.cpp15
-rw-r--r--src/corelib/text/qstring.h29
-rw-r--r--src/corelib/text/qstringliteral.h15
-rw-r--r--src/corelib/tools/qarraydata.cpp14
-rw-r--r--src/corelib/tools/qarraydata.h68
-rw-r--r--src/corelib/tools/qarraydataops.h4
-rw-r--r--src/corelib/tools/qarraydatapointer.h61
-rw-r--r--src/corelib/tools/qlist.h8
-rw-r--r--tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp2
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp6
-rw-r--r--tests/auto/corelib/tools/qarraydata/simplevector.h7
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp46
-rw-r--r--tests/auto/corelib/tools/qlist/tst_qlist.cpp50
-rw-r--r--tests/auto/tools/qmakelib/tst_qmakelib.cpp2
18 files changed, 202 insertions, 215 deletions
diff --git a/qmake/library/proitems.cpp b/qmake/library/proitems.cpp
index 85569ecd82..db19794bec 100644
--- a/qmake/library/proitems.cpp
+++ b/qmake/library/proitems.cpp
@@ -156,7 +156,8 @@ QString ProString::toQString() const
QString &ProString::toQString(QString &tmp) const
{
- return tmp.setRawData(m_string.constData() + m_offset, m_length);
+ tmp = m_string.mid(m_offset, m_length);
+ return tmp;
}
/*
diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h
index 6e091354e4..bef93795d2 100644
--- a/qmake/library/proitems.h
+++ b/qmake/library/proitems.h
@@ -270,7 +270,6 @@ class ProStringRoUser
public:
ProStringRoUser(QString &rs)
{
- Q_ASSERT(rs.isDetached() || rs.isEmpty());
m_rs = &rs;
}
ProStringRoUser(const ProString &ps, QString &rs)
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 95a1f9f52c..26e3b64c9d 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -67,6 +67,8 @@
QT_BEGIN_NAMESPACE
+const char QByteArray::_empty = '\0';
+
// ASCII case system, used by QByteArray::to{Upper,Lower}() and qstr(n)icmp():
static constexpr inline uchar asciiUpper(uchar c)
{
@@ -364,11 +366,18 @@ int qstrnicmp(const char *str1, const char *str2, uint len)
*/
int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2)
{
- Q_ASSERT(str1);
Q_ASSERT(len1 >= 0);
Q_ASSERT(len2 >= -1);
const uchar *s1 = reinterpret_cast<const uchar *>(str1);
const uchar *s2 = reinterpret_cast<const uchar *>(str2);
+ if (!s1 || !len1) {
+ if (len2 == 0)
+ return 0;
+ if (len2 == -1)
+ return (!s2 || !*s2) ? 0 : -1;
+ Q_ASSERT(s2);
+ return -1;
+ }
if (!s2)
return len1 == 0 ? 0 : 1;
@@ -1694,7 +1703,7 @@ void QByteArray::expand(int i)
QByteArray QByteArray::nulTerminated() const
{
// is this fromRawData?
- if (!IS_RAW_DATA(d))
+ if (d.isMutable())
return *this; // no, then we're sure we're zero terminated
QByteArray copy(*this);
@@ -1725,7 +1734,7 @@ QByteArray QByteArray::nulTerminated() const
QByteArray &QByteArray::prepend(const QByteArray &ba)
{
- if (size() == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) {
+ if (size() == 0 && d->isStatic() && ba.d.isMutable()) {
*this = ba;
} else if (ba.size() != 0) {
QByteArray tmp = *this;
@@ -1818,7 +1827,7 @@ QByteArray &QByteArray::prepend(char ch)
QByteArray &QByteArray::append(const QByteArray &ba)
{
- if (size() == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) {
+ if (size() == 0 && d->isStatic() && ba.d.isMutable()) {
*this = ba;
} else if (ba.size() != 0) {
if (d->needsDetach() || size() + ba.size() > capacity())
@@ -2507,6 +2516,8 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
{
+ if (isEmpty())
+ return !ba.size() ? 0 : -1;
const int ol = ba.size();
if (ol == 1)
return lastIndexOf(ba[0], from);
@@ -2524,6 +2535,8 @@ int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
*/
int QByteArray::lastIndexOf(const char *str, int from) const
{
+ if (isEmpty())
+ return (str && *str) ? -1 : 0;
const int ol = qstrlen(str);
if (ol == 1)
return lastIndexOf(*str, from);
@@ -3484,6 +3497,11 @@ T toIntegral_helper(const char *data, bool *ok, int base)
base = 10;
}
#endif
+ if (!data) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
// we select the right overload by the last, unused parameter
Int64 val = toIntegral_helper(data, ok, base, Int64());
@@ -4154,6 +4172,8 @@ QByteArray QByteArray::number(double n, char f, int prec)
}
/*!
+ \fn QByteArray QByteArray::fromRawData(const char *data, int size) constexpr
+
Constructs a QByteArray that uses the first \a size bytes of the
\a data array. The bytes are \e not copied. The QByteArray will
contain the \a data pointer. The caller guarantees that \a data
@@ -4187,18 +4207,6 @@ QByteArray QByteArray::number(double n, char f, int prec)
\sa setRawData(), data(), constData()
*/
-QByteArray QByteArray::fromRawData(const char *data, int size)
-{
- QByteArray::DataPointer x;
- if (!data) {
- } else if (!size) {
- x = DataPointer(Data::allocate(0), 0);
- } else {
- x = Data::fromRawData(data, size);
- }
- return QByteArray(x);
-}
-
/*!
\since 4.7
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index 5cbcecb956..c2ec72ae76 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -54,6 +54,11 @@
#include <string>
#include <iterator>
+#ifndef QT5_NULL_STRINGS
+// ### Should default to 0 in Qt 6.0
+#define QT5_NULL_STRINGS 1
+#endif
+
#ifdef truncate
#error qbytearray.h must be included before any header file that defines truncate
#endif
@@ -117,16 +122,7 @@ class QDataStream;
using QByteArrayData = QArrayDataPointer<char>;
# define QByteArrayLiteral(str) \
- ([]() -> QByteArray { \
- enum { Size = sizeof(str) - 1 }; \
- static const QArrayData qbytearray_literal = { \
- Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }; \
- QByteArrayData holder = { \
- static_cast<QTypedArrayData<char> *>(const_cast<QArrayData *>(&qbytearray_literal)), \
- const_cast<char *>(str), \
- Size }; \
- return QByteArray(holder); \
- }()) \
+ (QByteArray(QByteArrayData(nullptr, const_cast<char *>(str), sizeof(str) - 1))) \
/**/
class Q_CORE_EXPORT QByteArray
@@ -137,6 +133,7 @@ private:
typedef QTypedArrayData<char> Data;
DataPointer d;
+ static const char _empty;
public:
enum Base64Option {
@@ -158,7 +155,7 @@ public:
IllegalPadding,
};
- inline QByteArray() noexcept;
+ inline constexpr QByteArray() noexcept;
QByteArray(const char *, int size = -1);
QByteArray(int size, char c);
QByteArray(int size, Qt::Initialization);
@@ -357,7 +354,10 @@ public:
Q_REQUIRED_RESULT static QByteArray number(qlonglong, int base = 10);
Q_REQUIRED_RESULT static QByteArray number(qulonglong, int base = 10);
Q_REQUIRED_RESULT static QByteArray number(double, char f = 'g', int prec = 6);
- Q_REQUIRED_RESULT static QByteArray fromRawData(const char *, int size);
+ Q_REQUIRED_RESULT static QByteArray fromRawData(const char *data, int size)
+ {
+ return QByteArray(DataPointer(nullptr, const_cast<char *>(data), size));
+ }
class FromBase64Result;
Q_REQUIRED_RESULT static FromBase64Result fromBase64Encoding(QByteArray &&base64, Base64Options options = Base64Encoding);
@@ -449,7 +449,7 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options)
-inline QByteArray::QByteArray() noexcept {}
+inline constexpr QByteArray::QByteArray() noexcept {}
inline QByteArray::~QByteArray() {}
inline char QByteArray::at(int i) const
@@ -466,11 +466,21 @@ inline QByteArray::operator const void *() const
{ return data(); }
#endif
inline char *QByteArray::data()
-{ detach(); return d.data(); }
+{
+ detach();
+ Q_ASSERT(d.data());
+ return d.data();
+}
inline const char *QByteArray::data() const
-{ return d.data(); }
+{
+#if QT5_NULL_STRINGS == 1
+ return d.data() ? d.data() : &_empty;
+#else
+ return d.data();
+#endif
+}
inline const char *QByteArray::constData() const
-{ return d.data(); }
+{ return data(); }
inline void QByteArray::detach()
{ if (d->needsDetach()) reallocData(uint(size()) + 1u, d->detachFlags()); }
inline bool QByteArray::isDetached() const
@@ -486,7 +496,7 @@ inline void QByteArray::reserve(int asize)
if (d->needsDetach() || asize > capacity()) {
reallocData(qMax(uint(size()), uint(asize)) + 1u, d->detachFlags() | Data::CapacityReserved);
} else {
- d->flags() |= Data::CapacityReserved;
+ d->setFlag(Data::CapacityReserved);
}
}
@@ -497,7 +507,7 @@ inline void QByteArray::squeeze()
if (d->needsDetach() || size() < capacity()) {
reallocData(uint(size()) + 1u, d->detachFlags() & ~Data::CapacityReserved);
} else {
- d->flags() &= uint(~Data::CapacityReserved);
+ d->clearFlag(Data::CapacityReserved);
}
}
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index d327264218..af3be9ab9f 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -106,6 +106,8 @@ static constexpr bool points_into_range(const T *p, const T *b, const T *e, Cmp
return !less(p, b) && less(p, e);
}
+const char16_t QString::_empty = 0;
+
/*
* Note on the use of SIMD in qstring.cpp:
*
@@ -4549,7 +4551,7 @@ QString QString::mid(int position, int n) const
{
QPair<Data *, char16_t *> pair = Data::allocate(0);
DataPointer empty = { pair.first, pair.second, 0 };
- return QString(empty);
+ return QString(std::move(empty));
}
case QContainerImplHelper::Full:
return *this;
@@ -5066,7 +5068,7 @@ QString QString::fromLocal8Bit_helper(const char *str, int size)
if (size == 0 || (!*str && size < 0)) {
QPair<Data *, char16_t *> pair = Data::allocate(0);
QString::DataPointer empty = { pair.first, pair.second, 0 };
- return QString(empty);
+ return QString(std::move(empty));
}
QStringDecoder toUtf16(QStringDecoder::System, QStringDecoder::Flag::Stateless);
return toUtf16(str, size);
@@ -8617,14 +8619,7 @@ bool QString::isRightToLeft() const
*/
QString QString::fromRawData(const QChar *unicode, int size)
{
- QString::DataPointer x;
- if (!unicode) {
- } else if (!size) {
- x = DataPointer(Data::allocate(0), 0);
- } else {
- x = Data::fromRawData(reinterpret_cast<const char16_t *>(unicode), size);
- }
- return QString(x);
+ return QString(Data::fromRawData(const_cast<char16_t *>(reinterpret_cast<const char16_t *>(unicode)), size));
}
/*!
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 95376f79c0..da553ddde4 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -275,7 +275,7 @@ class Q_CORE_EXPORT QString
public:
typedef QStringPrivate DataPointer;
- inline QString() noexcept;
+ inline constexpr QString() noexcept;
explicit QString(const QChar *unicode, int size = -1);
QString(QChar c);
QString(int size, QChar c);
@@ -902,7 +902,7 @@ public:
{ return QStringView(*this).isValidUtf16(); }
QString(int size, Qt::Initialization);
- explicit QString(DataPointer dd) : d(dd) {}
+ explicit QString(DataPointer &&dd) : d(std::move(dd)) {}
private:
#if defined(QT_NO_CAST_FROM_ASCII)
@@ -915,6 +915,7 @@ private:
#endif
DataPointer d;
+ static const char16_t _empty;
friend inline bool operator==(QChar, const QString &) noexcept;
friend inline bool operator< (QChar, const QString &) noexcept;
@@ -1031,13 +1032,23 @@ inline const QChar QString::operator[](int i) const
inline bool QString::isEmpty() const
{ return d.size == 0; }
inline const QChar *QString::unicode() const
-{ return reinterpret_cast<const QChar*>(d.data()); }
+{ return data(); }
inline const QChar *QString::data() const
-{ return reinterpret_cast<const QChar*>(d.data()); }
+{
+#if QT5_NULL_STRINGS == 1
+ return reinterpret_cast<const QChar *>(d.data() ? d.data() : &_empty);
+#else
+ return reinterpret_cast<const QChar *>(d.data());
+#endif
+}
inline QChar *QString::data()
-{ detach(); return reinterpret_cast<QChar*>(d.data()); }
+{
+ detach();
+ Q_ASSERT(d.data());
+ return reinterpret_cast<QChar *>(d.data());
+}
inline const QChar *QString::constData() const
-{ return reinterpret_cast<const QChar*>(d.data()); }
+{ return data(); }
inline void QString::detach()
{ if (d->needsDetach()) reallocData(d.size + 1u); }
inline bool QString::isDetached() const
@@ -1107,7 +1118,7 @@ inline QString QString::fromWCharArray(const wchar_t *string, int size)
: fromUcs4(reinterpret_cast<const char32_t *>(string), size);
}
-inline QString::QString() noexcept {}
+inline constexpr QString::QString() noexcept {}
inline QString::~QString() {}
inline void QString::reserve(int asize)
@@ -1116,7 +1127,7 @@ inline void QString::reserve(int asize)
reallocData(uint(qMax(asize, size())) + 1u);
// we're not shared anymore, for sure
- d->flags() |= Data::CapacityReserved;
+ d->setFlag(Data::CapacityReserved);
}
inline void QString::squeeze()
@@ -1127,7 +1138,7 @@ inline void QString::squeeze()
reallocData(uint(d.size) + 1u);
// we're not shared anymore, for sure
- d->flags() &= uint(~Data::CapacityReserved);
+ d->clearFlag(Data::CapacityReserved);
}
inline QString &QString::setUtf16(const ushort *autf16, int asize)
diff --git a/src/corelib/text/qstringliteral.h b/src/corelib/text/qstringliteral.h
index a44787c7a4..4d24937eb7 100644
--- a/src/corelib/text/qstringliteral.h
+++ b/src/corelib/text/qstringliteral.h
@@ -62,18 +62,9 @@ static_assert(sizeof(qunicodechar) == 2,
#define QT_UNICODE_LITERAL(str) u"" str
#define QStringLiteral(str) \
- ([]() noexcept -> QString { \
- enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
- static const QArrayData qstring_literal = { \
- Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 \
- }; \
- QStringPrivate holder = { \
- static_cast<QTypedArrayData<char16_t> *>(const_cast<QArrayData *>(&qstring_literal)), \
- const_cast<qunicodechar *>(QT_UNICODE_LITERAL(str)), \
- Size \
- }; \
- return QString(holder); \
- }()) \
+ (QString(QStringPrivate(nullptr, \
+ reinterpret_cast<char16_t *>(const_cast<qunicodechar *>(QT_UNICODE_LITERAL(str))), \
+ sizeof(QT_UNICODE_LITERAL(str))/2 - 1))) \
/**/
using QStringPrivate = QArrayDataPointer<char16_t>;
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 514dd7c4de..9330a01a87 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -232,25 +232,15 @@ void *QArrayData::allocate(QArrayData **dptr, size_t objectSize, size_t alignmen
return reinterpret_cast<void *>(data);
}
-QArrayData *QArrayData::prepareRawData(ArrayOptions options) Q_DECL_NOTHROW
-{
- QArrayData *header = allocateData(sizeof(QArrayData), (options & ~DataTypeBits) | RawDataType);
- if (header)
- header->alloc = 0;
- return header;
-}
-
QPair<QArrayData *, void *>
QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
size_t objectSize, size_t capacity, ArrayOptions options) noexcept
{
- Q_ASSERT(data);
- Q_ASSERT(data->isMutable());
- Q_ASSERT(!data->isShared());
+ Q_ASSERT(!data || !data->isShared());
size_t headerSize = sizeof(QArrayData);
size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- qptrdiff offset = reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data);
+ qptrdiff offset = dataPointer ? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data) : headerSize;
options |= AllocatedDataType | MutableData;
QArrayData *header = static_cast<QArrayData *>(::realloc(data, size_t(allocSize)));
if (header) {
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index ed2c7a41c1..d0a285a0e9 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -143,14 +143,6 @@ struct Q_CORE_EXPORT QArrayData
return result;
}
- ArrayOptions cloneFlags() const
- {
- ArrayOptions result = DefaultAllocationFlags;
- if (flags & CapacityReserved)
- result |= CapacityReserved;
- return result;
- }
-
Q_REQUIRED_RESULT
#if defined(Q_CC_GNU)
__attribute__((__malloc__))
@@ -159,8 +151,6 @@ struct Q_CORE_EXPORT QArrayData
size_t capacity, ArrayOptions options = DefaultAllocationFlags) noexcept;
Q_REQUIRED_RESULT static QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
size_t objectSize, size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT static QArrayData *prepareRawData(ArrayOptions options = ArrayOptions(RawDataType))
- Q_DECL_NOTHROW;
static void deallocate(QArrayData *data, size_t objectSize,
size_t alignment) noexcept;
@@ -229,36 +219,14 @@ struct QTypedArrayData
QArrayData::deallocate(data, sizeof(T), alignof(AlignmentDummy));
}
- static QArrayDataPointerRef<T> fromRawData(const T *data, size_t n,
- ArrayOptions options = DefaultRawFlags)
+ static QArrayDataPointerRef<T> fromRawData(const T *data, size_t n)
{
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
QArrayDataPointerRef<T> result = {
- static_cast<QTypedArrayData *>(prepareRawData(options)), const_cast<T *>(data), uint(n)
+ nullptr, const_cast<T *>(data), uint(n)
};
- if (result.ptr) {
- Q_ASSERT(!result.ptr->isShared()); // No shared empty, please!
- }
return result;
}
-
- static QTypedArrayData *sharedNull() noexcept
- {
- static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return static_cast<QTypedArrayData *>(QArrayData::sharedNull());
- }
-
- static QTypedArrayData *sharedEmpty()
- {
- static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return allocate(/* capacity */ 0);
- }
-
- static T *sharedNullData()
- {
- static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
- return static_cast<T *>(QArrayData::sharedNullData());
- }
};
////////////////////////////////////////////////////////////////////////////////
@@ -271,33 +239,11 @@ struct QTypedArrayData
// Hide array inside a lambda
#define Q_ARRAY_LITERAL(Type, ...) \
- ([]() -> QArrayDataPointerRef<Type> { \
- /* MSVC 2010 Doesn't support static variables in a lambda, but */ \
- /* happily accepts them in a static function of a lambda-local */ \
- /* struct :-) */ \
- struct StaticWrapper { \
- static QArrayDataPointerRef<Type> get() \
- { \
- Q_ARRAY_LITERAL_IMPL(Type, __VA_ARGS__) \
- return ref; \
- } \
- }; \
- return StaticWrapper::get(); \
- }()) \
- /**/
-
-#define Q_ARRAY_LITERAL_IMPL(Type, ...) \
- /* Portable compile-time array size computation */ \
- static constexpr Type data[] = { __VA_ARGS__ }; \
- enum { Size = sizeof(data) / sizeof(data[0]) }; \
- \
- static constexpr QArrayData literal = { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 };\
- \
- QArrayDataPointerRef<Type> ref = \
- { static_cast<QTypedArrayData<Type> *>( \
- const_cast<QArrayData *>(&literal)), \
- const_cast<Type *>(data), \
- Size }; \
+ ([]() -> QArrayDataPointerRef<Type> { \
+ static Type const data[] = { __VA_ARGS__ }; \
+ enum { Size = sizeof(data) / sizeof(data[0]) }; \
+ return { nullptr, const_cast<Type *>(data), Size }; \
+ }())
/**/
namespace QtPrivate {
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 33ad13c6b7..bea585e69a 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -134,7 +134,7 @@ public:
void destroyAll() // Call from destructors, ONLY!
{
- Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->d);
Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
// As this is to be called only from destructor, it doesn't need to be
@@ -334,7 +334,7 @@ struct QGenericArrayOps
void destroyAll() // Call from destructors, ONLY
{
- Q_ASSERT(this->isMutable());
+ Q_ASSERT(this->d);
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index 9bdbea2bde..a8b472c9bf 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -59,18 +59,18 @@ public:
typedef typename std::conditional<pass_parameter_by_value, T, const T &>::type parameter_type;
- QArrayDataPointer() noexcept
- : d(Data::sharedNull()), ptr(Data::sharedNullData()), size(0)
+ constexpr QArrayDataPointer() noexcept
+ : d(nullptr), ptr(nullptr), size(0)
{
}
QArrayDataPointer(const QArrayDataPointer &other) noexcept
: d(other.d), ptr(other.ptr), size(other.size)
{
- other.d->ref();
+ ref();
}
- QArrayDataPointer(Data *header, T *adata, size_t n = 0) noexcept
+ constexpr QArrayDataPointer(Data *header, T *adata, size_t n = 0) noexcept
: d(header), ptr(adata), size(int(n))
{
}
@@ -96,54 +96,48 @@ public:
QArrayDataPointer(QArrayDataPointer &&other) noexcept
: d(other.d), ptr(other.ptr), size(other.size)
{
- other.d = Data::sharedNull();
- other.ptr = Data::sharedNullData();
+ other.d = nullptr;
+ other.ptr = nullptr;
other.size = 0;
}
QArrayDataPointer &operator=(QArrayDataPointer &&other) noexcept
{
- QArrayDataPointer moved(std::move(other));
- this->swap(moved);
+ this->swap(other);
return *this;
}
DataOps &operator*() noexcept
{
- Q_ASSERT(d);
return *static_cast<DataOps *>(this);
}
DataOps *operator->() noexcept
{
- Q_ASSERT(d);
return static_cast<DataOps *>(this);
}
const DataOps &operator*() const noexcept
{
- Q_ASSERT(d);
return *static_cast<const DataOps *>(this);
}
const DataOps *operator->() const noexcept
{
- Q_ASSERT(d);
return static_cast<const DataOps *>(this);
}
~QArrayDataPointer()
{
if (!deref()) {
- if (isMutable())
- (*this)->destroyAll();
+ (*this)->destroyAll();
Data::deallocate(d);
}
}
bool isNull() const noexcept
{
- return d == Data::sharedNull();
+ return !ptr;
}
T *data() noexcept { return ptr; }
@@ -171,8 +165,8 @@ public:
bool detach()
{
- if (d->needsDetach()) {
- QPair<Data *, T *> copy = clone(d->detachFlags());
+ if (needsDetach()) {
+ QPair<Data *, T *> copy = clone(detachFlags());
QArrayDataPointer old(d, ptr, size);
d = copy.first;
ptr = copy.second;
@@ -183,36 +177,35 @@ public:
}
// forwards from QArrayData
- size_t allocatedCapacity() noexcept { return d->allocatedCapacity(); }
- size_t constAllocatedCapacity() const noexcept { return d->constAllocatedCapacity(); }
- int refCounterValue() const noexcept { return d->refCounterValue(); }
- bool ref() noexcept { return d->ref(); }
- bool deref() noexcept { return d->deref(); }
- bool isMutable() const noexcept { return d->isMutable(); }
- bool isStatic() const noexcept { return d->isStatic(); }
- bool isShared() const noexcept { return d->isShared(); }
+ size_t allocatedCapacity() noexcept { return d ? d->allocatedCapacity() : 0; }
+ size_t constAllocatedCapacity() const noexcept { return d ? d->constAllocatedCapacity() : 0; }
+ void ref() noexcept { if (d) d->ref(); }
+ bool deref() noexcept { return !d || d->deref(); }
+ bool isMutable() const noexcept { return d; }
+ bool isStatic() const noexcept { return !d; }
+ bool isShared() const noexcept { return !d || d->isShared(); }
bool isSharedWith(const QArrayDataPointer &other) const noexcept { return d && d == other.d; }
- bool needsDetach() const noexcept { return d->needsDetach(); }
- size_t detachCapacity(size_t newSize) const noexcept { return d->detachCapacity(newSize); }
- typename Data::ArrayOptions &flags() noexcept { return reinterpret_cast<typename Data::ArrayOptions &>(d->flags); }
- typename Data::ArrayOptions flags() const noexcept { return typename Data::ArrayOption(d->flags); }
- typename Data::ArrayOptions detachFlags() const noexcept { return d->detachFlags(); }
- typename Data::ArrayOptions cloneFlags() const noexcept { return d->cloneFlags(); }
+ bool needsDetach() const noexcept { return !d || d->needsDetach(); }
+ size_t detachCapacity(size_t newSize) const noexcept { return d ? d->detachCapacity(newSize) : newSize; }
+ const typename Data::ArrayOptions flags() const noexcept { return d ? typename Data::ArrayOption(d->flags) : Data::DefaultAllocationFlags; }
+ void setFlag(typename Data::ArrayOptions f) { Q_ASSERT(d); d->flags |= f; }
+ void clearFlag(typename Data::ArrayOptions f) { Q_ASSERT(d); d->flags &= ~f; }
+ typename Data::ArrayOptions detachFlags() const noexcept { return d ? d->detachFlags() : Data::DefaultAllocationFlags; }
Data *d_ptr() { return d; }
private:
Q_REQUIRED_RESULT QPair<Data *, T *> clone(QArrayData::ArrayOptions options) const
{
- QPair<Data *, T *> pair = Data::allocate(d->detachCapacity(size),
- options);
+ QPair<Data *, T *> pair = Data::allocate(detachCapacity(size), options);
Q_CHECK_PTR(pair.first);
QArrayDataPointer copy(pair.first, pair.second, 0);
if (size)
copy->copyAppend(begin(), end());
pair.first = copy.d;
- copy.d = Data::sharedNull();
+ copy.d = nullptr;
+ copy.ptr = nullptr;
return pair;
}
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 5d0a95fb0b..c37a2fd97c 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -428,6 +428,12 @@ public:
static inline QList<T> fromVector(const QList<T> &vector) { return vector; }
inline QList<T> toVector() const { return *this; }
+
+ template<int N>
+ static QList<T> fromReadOnlyData(const T (&t)[N])
+ {
+ return QList<T>({ nullptr, const_cast<T *>(t), N });
+ }
};
#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
@@ -465,7 +471,7 @@ void QList<T>::reserve(int asize)
return; // already reserved, don't shrink
if (!d->isShared()) {
// accept current allocation, don't shrink
- d->flags() |= Data::CapacityReserved;
+ d->setFlag(Data::CapacityReserved);
return;
}
}
diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
index 73d9f8e765..940865b98e 100644
--- a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
@@ -2277,7 +2277,7 @@ void tst_QByteArray::literals()
QVERIFY(str.length() == 4);
QCOMPARE(str.capacity(), 0);
QVERIFY(str == "abcd");
- QVERIFY(str.data_ptr()->isStatic());
+ QVERIFY(!str.data_ptr()->isMutable());
const char *s = str.constData();
QByteArray str2 = str;
diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp
index 81a08eb59e..4d2e91a694 100644
--- a/tests/auto/corelib/text/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -4014,7 +4014,7 @@ void tst_QString::fromRawData()
{
const QChar ptr[] = { 0x1234, 0x0000 };
QString cstr = QString::fromRawData(ptr, 1);
- QVERIFY(cstr.isDetached());
+ QVERIFY(!cstr.isDetached());
QVERIFY(cstr.constData() == ptr);
QVERIFY(cstr == QString(ptr, 1));
cstr.squeeze();
@@ -4036,7 +4036,7 @@ void tst_QString::setRawData()
// This just tests the fromRawData() fallback
QVERIFY(!cstr.isDetached());
cstr.setRawData(ptr, 1);
- QVERIFY(cstr.isDetached());
+ QVERIFY(!cstr.isDetached());
QVERIFY(cstr.constData() == ptr);
QVERIFY(cstr == QString(ptr, 1));
@@ -6571,7 +6571,7 @@ void tst_QString::literals()
QVERIFY(str.length() == 4);
QCOMPARE(str.capacity(), 0);
QVERIFY(str == QLatin1String("abcd"));
- QVERIFY(str.data_ptr()->isStatic());
+ QVERIFY(!str.data_ptr()->isMutable());
const QChar *s = str.constData();
QString str2 = str;
diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h
index 94cee5d887..1a9ed35b7a 100644
--- a/tests/auto/corelib/tools/qarraydata/simplevector.h
+++ b/tests/auto/corelib/tools/qarraydata/simplevector.h
@@ -153,7 +153,7 @@ public:
if (d->flags() & Data::CapacityReserved)
return;
if (!d->isShared()) {
- d->flags() |= Data::CapacityReserved;
+ d.setFlag(Data::CapacityReserved);
return;
}
}
@@ -338,10 +338,9 @@ public:
d.detach();
}
- static SimpleVector fromRawData(const T *data, size_t size,
- QArrayData::ArrayOptions options = Data::DefaultRawFlags)
+ static SimpleVector fromRawData(const T *data, size_t size)
{
- return SimpleVector(Data::fromRawData(data, size, options));
+ return SimpleVector(Data::fromRawData(data, size));
}
private:
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
index 7b42b27f6e..128bc51553 100644
--- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
+++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
@@ -156,20 +156,15 @@ void tst_QArrayData::sharedNullEmpty()
void tst_QArrayData::simpleVector()
{
- QArrayData data0 = { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 };
- QStaticArrayData<int, 7> data1 = {
- { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 },
- { 0, 1, 2, 3, 4, 5, 6 }
- };
-
+ int data[] = { 0, 1, 2, 3, 4, 5, 6 };
int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
SimpleVector<int> v1;
SimpleVector<int> v2(v1);
- SimpleVector<int> v3(static_cast<QTypedArrayData<int> *>(&data0), 0, 0);
- SimpleVector<int> v4(data1);
- SimpleVector<int> v5(static_cast<QTypedArrayData<int> *>(&data0), 0, 0);
- SimpleVector<int> v6(data1);
+ SimpleVector<int> v3(nullptr, nullptr, 0);
+ SimpleVector<int> v4(nullptr, data, 0);
+ SimpleVector<int> v5(nullptr, data, 1);
+ SimpleVector<int> v6(nullptr, data, 7);
SimpleVector<int> v7(10, 5);
SimpleVector<int> v8(array, array + sizeof(array)/sizeof(*array));
@@ -190,7 +185,7 @@ void tst_QArrayData::simpleVector()
QVERIFY(v2.isEmpty());
QVERIFY(v3.isEmpty());
QVERIFY(v4.isEmpty());
- QVERIFY(v5.isEmpty());
+ QVERIFY(!v5.isEmpty());
QVERIFY(!v6.isEmpty());
QVERIFY(!v7.isEmpty());
QVERIFY(!v8.isEmpty());
@@ -199,7 +194,7 @@ void tst_QArrayData::simpleVector()
QCOMPARE(v2.size(), size_t(0));
QCOMPARE(v3.size(), size_t(0));
QCOMPARE(v4.size(), size_t(0));
- QCOMPARE(v5.size(), size_t(0));
+ QCOMPARE(v5.size(), size_t(1));
QCOMPARE(v6.size(), size_t(7));
QCOMPARE(v7.size(), size_t(10));
QCOMPARE(v8.size(), size_t(10));
@@ -248,13 +243,13 @@ void tst_QArrayData::simpleVector()
QVERIFY(v1 == v2);
QVERIFY(v1 == v3);
QVERIFY(v1 == v4);
- QVERIFY(v1 == v5);
+ QVERIFY(v1 != v5);
QVERIFY(!(v1 == v6));
QVERIFY(v1 != v6);
QVERIFY(v4 != v6);
QVERIFY(v5 != v6);
- QVERIFY(!(v1 != v5));
+ QVERIFY(!(v1 == v5));
QVERIFY(v1 < v6);
QVERIFY(!(v6 < v1));
@@ -428,17 +423,10 @@ void tst_QArrayData::simpleVectorReserve_data()
QTest::newRow("empty") << SimpleVector<int>(0, 42) << size_t(0) << size_t(0);
QTest::newRow("non-empty") << SimpleVector<int>(5, 42) << size_t(5) << size_t(5);
- static const QStaticArrayData<int, 15> array = {
- { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 },
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } };
- const QArrayDataPointerRef<int> p = {
- static_cast<QTypedArrayData<int> *>(
- const_cast<QArrayData *>(&array.header)),
- const_cast<int *>(array.data),
- sizeof(array.data) / sizeof(array.data[0]) };
-
- QTest::newRow("static") << SimpleVector<int>(p) << size_t(0) << size_t(15);
- QTest::newRow("raw-data") << SimpleVector<int>::fromRawData(array.data, 15) << size_t(0) << size_t(15);
+ static const int array[] =
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ QTest::newRow("raw-data") << SimpleVector<int>::fromRawData(array, 15) << size_t(0) << size_t(15);
}
void tst_QArrayData::simpleVectorReserve()
@@ -519,7 +507,7 @@ void tst_QArrayData::allocate_data()
};
QArrayData *shared_empty;
- QArrayData::allocate(&shared_empty, 1, alignof(QArrayData), 0);
+ (void)QArrayData::allocate(&shared_empty, 1, alignof(QArrayData), 0);
QVERIFY(shared_empty);
struct {
@@ -1180,15 +1168,15 @@ void fromRawData_impl()
{
// Default: Immutable, sharable
SimpleVector<T> raw = SimpleVector<T>::fromRawData(array,
- sizeof(array)/sizeof(array[0]), QArrayData::DefaultRawFlags);
+ sizeof(array)/sizeof(array[0]));
QCOMPARE(raw.size(), size_t(11));
QCOMPARE((const T *)raw.constBegin(), array);
QCOMPARE((const T *)raw.constEnd(), (const T *)(array + sizeof(array)/sizeof(array[0])));
- QVERIFY(!raw.isShared());
+ QVERIFY(raw.isShared());
QVERIFY(SimpleVector<T>(raw).isSharedWith(raw));
- QVERIFY(!raw.isShared());
+ QVERIFY(raw.isShared());
// Detach
QCOMPARE(raw.back(), T(11));
diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
index df3f2023d6..ddf5e9c30a 100644
--- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp
+++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
@@ -336,6 +336,8 @@ private slots:
void emplaceWithElementFromTheSameContainer();
void emplaceWithElementFromTheSameContainer_data();
+ void fromReadOnlyData() const;
+
private:
template<typename T> void copyConstructor() const;
template<typename T> void add() const;
@@ -2830,5 +2832,53 @@ void tst_QList::emplaceConsistentWithStdVectorImpl() const
vecEq(qVec, stdVec);
}
+void tst_QList::fromReadOnlyData() const
+{
+ {
+ QVector<char> d = QVector<char>::fromReadOnlyData("ABCDEFGHIJ");
+ QCOMPARE(d.size(), 10u + 1u);
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(d.data()[i], char('A' + i));
+ }
+
+ {
+ // wchar_t is not necessarily 2-bytes
+ QVector<wchar_t> d = QVector<wchar_t>::fromReadOnlyData(L"ABCDEFGHIJ");
+ QCOMPARE(d.size(), 10u + 1u);
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(d.data()[i], wchar_t('A' + i));
+ QVERIFY(d.isDetached());
+ }
+
+ {
+ const char data[] = "ABCDEFGHIJ";
+ const QVector<char> v = QVector<char>::fromReadOnlyData(data);
+
+ QVERIFY(v.constData() == data);
+ QVERIFY(!v.isEmpty());
+ QCOMPARE(v.size(), size_t(11));
+ // v.capacity() is unspecified, for now
+
+ QCOMPARE((void*)(const char*)(v.constBegin() + v.size()), (void*)(const char*)v.constEnd());
+
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(v[i], char('A' + i));
+ QCOMPARE(v[10], char('\0'));
+ }
+
+ {
+ struct LiteralType {
+ int value;
+ Q_DECL_CONSTEXPR LiteralType(int v = 0) : value(v) {}
+ };
+ const LiteralType literal[] = {LiteralType(0), LiteralType(1), LiteralType(2)};
+
+ const QVector<LiteralType> d = QVector<LiteralType>::fromReadOnlyData(literal);
+ QCOMPARE(d.size(), 3);
+ for (int i = 0; i < 3; ++i)
+ QCOMPARE(d.data()[i].value, i);
+ }
+}
+
QTEST_MAIN(tst_QList)
#include "tst_qlist.moc"
diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.cpp b/tests/auto/tools/qmakelib/tst_qmakelib.cpp
index 3d66f940ff..a699a0575e 100644
--- a/tests/auto/tools/qmakelib/tst_qmakelib.cpp
+++ b/tests/auto/tools/qmakelib/tst_qmakelib.cpp
@@ -56,7 +56,7 @@ void tst_qmakelib::cleanupTestCase()
void tst_qmakelib::proString()
{
- QString qs1(QStringLiteral("this is a string"));
+ QString qs1(QString::fromUtf8("this is a string"));
ProString s1(qs1);
QCOMPARE(s1.toQString(), QStringLiteral("this is a string"));