From a5233b6b22e20bf249d8ae993a4224c6874abccf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20Abecasis?= Date: Fri, 17 Feb 2012 14:18:45 +0100 Subject: [PATCH] Change meaning of offset in QStringData It used to be an index into the first element in 'd' that came after 'offset'. It is now the byte offset from the beginning of the QStringData structure. By no longer using an actual array to access characters, we also steer clear of GCC bug #43247: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43247 This aligns this data structure with QArrayData. The intention is to have QVector, QString and QByteArray share the same memory layout and possibly code. Change-Id: I4850813e1bd47c3cb670c50c9a8ccc1bff2e8597 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 32 +++++++++++++----------- src/corelib/tools/qstring.h | 17 ++++++------- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 2 +- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 5721090..be6f488 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -94,6 +94,8 @@ #define ULLONG_MAX quint64_C(18446744073709551615) #endif +#define IS_RAW_DATA(d) ((d)->offset != sizeof(QStringData)) + QT_BEGIN_NAMESPACE #ifndef QT_NO_TEXTCODEC @@ -800,8 +802,8 @@ const QString::Null QString::null = { }; \sa split() */ -const QStaticStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, { 0 } }, { 0 } }; -const QStaticStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, { 0 } }, { 0 } }; +const QStaticStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, sizeof(QStringData) }, { 0 } }; +const QStaticStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, sizeof(QStringData) }, { 0 } }; int QString::grow(int size) { @@ -1052,7 +1054,7 @@ QString::QString(const QChar *unicode, int size) d->size = size; d->alloc = (uint) size; d->capacityReserved = false; - d->offset = 0; + d->offset = sizeof(QStringData); memcpy(d->data(), unicode, size * sizeof(QChar)); d->data()[size] = '\0'; } @@ -1076,7 +1078,7 @@ QString::QString(int size, QChar ch) d->size = size; d->alloc = (uint) size; d->capacityReserved = false; - d->offset = 0; + d->offset = sizeof(QStringData); d->data()[size] = '\0'; ushort *i = d->data() + size; ushort *b = d->data(); @@ -1100,7 +1102,7 @@ QString::QString(int size, Qt::Initialization) d->size = size; d->alloc = (uint) size; d->capacityReserved = false; - d->offset = 0; + d->offset = sizeof(QStringData); d->data()[size] = '\0'; } @@ -1122,7 +1124,7 @@ QString::QString(QChar ch) d->size = 1; d->alloc = 1; d->capacityReserved = false; - d->offset = 0; + d->offset = sizeof(QStringData); d->data()[0] = ch.unicode(); d->data()[1] = '\0'; } @@ -1220,7 +1222,7 @@ void QString::resize(int size) if (size < 0) size = 0; - if (d->offset && !d->ref.isShared() && size < d->size) { + if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) { d->size = size; return; } @@ -1294,14 +1296,14 @@ void QString::resize(int size) // ### Qt 5: rename reallocData() to avoid confusion. 197625 void QString::realloc(int alloc) { - if (d->ref.isShared() || d->offset) { + if (d->ref.isShared() || IS_RAW_DATA(d)) { Data *x = static_cast(::malloc(sizeof(Data) + (alloc+1) * sizeof(QChar))); Q_CHECK_PTR(x); x->ref.initializeOwned(); x->size = qMin(alloc, d->size); x->alloc = (uint) alloc; x->capacityReserved = d->capacityReserved; - x->offset =0; + x->offset = sizeof(QStringData); ::memcpy(x->data(), d->data(), x->size * sizeof(QChar)); x->data()[x->size] = 0; if (!d->ref.deref()) @@ -1312,7 +1314,7 @@ void QString::realloc(int alloc) Q_CHECK_PTR(p); d = p; d->alloc = alloc; - d->offset = 0; + d->offset = sizeof(QStringData); } } @@ -3741,7 +3743,7 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size) d->size = size; d->alloc = (uint) size; d->capacityReserved = false; - d->offset = 0; + d->offset = sizeof(QStringData); d->data()[size] = '\0'; ushort *dst = d->data(); /* SIMD: @@ -4769,7 +4771,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, const ushort *QString::utf16() const { - if (d->offset) + if (IS_RAW_DATA(d)) const_cast(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings return d->data(); } @@ -7050,7 +7052,7 @@ QString QString::fromRawData(const QChar *unicode, int size) x->size = size; x->alloc = 0; x->capacityReserved = false; - x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort)); + x->offset = reinterpret_cast(unicode) - reinterpret_cast(x); } return QString(x, 0); } @@ -7076,9 +7078,9 @@ QString &QString::setRawData(const QChar *unicode, int size) } else { if (unicode) { d->size = size; - d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort)); + d->offset = reinterpret_cast(unicode) - reinterpret_cast(d); } else { - d->offset = 0; + d->offset = sizeof(QStringData); d->size = 0; } } diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index df0ce73..90fed78 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -75,12 +75,11 @@ struct QStringData { int size; uint alloc : 31; uint capacityReserved : 1; - union { - qptrdiff offset; // will always work as we add/subtract from a ushort ptr - ushort d[sizeof(qptrdiff)/sizeof(ushort)]; - }; - inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } - inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } + + qptrdiff offset; + + inline ushort *data() { return reinterpret_cast(reinterpret_cast(this) + offset); } + inline const ushort *data() const { return reinterpret_cast(reinterpret_cast(this) + offset); } }; template struct QStaticStringData; @@ -126,7 +125,7 @@ template struct QStaticStringData # define QStringLiteral(str) ([]() -> QStaticStringDataPtr { \ enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \ static const QStaticStringData qstring_literal = \ - { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \ + { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QStringData) }, QT_UNICODE_LITERAL(str) }; \ QStaticStringDataPtr holder = { &qstring_literal }; \ return holder; }()) @@ -139,7 +138,7 @@ template struct QStaticStringData __extension__ ({ \ enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \ static const QStaticStringData qstring_literal = \ - { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \ + { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QStringData) }, QT_UNICODE_LITERAL(str) }; \ QStaticStringDataPtr holder = { &qstring_literal }; \ holder; }) # endif @@ -705,7 +704,7 @@ inline QChar *QString::data() inline const QChar *QString::constData() const { return reinterpret_cast(d->data()); } inline void QString::detach() -{ if (d->ref.isShared() || d->offset) realloc(); } +{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) realloc(); } inline bool QString::isDetached() const { return !d->ref.isShared(); } inline QString &QString::operator=(const QLatin1String &s) diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index e380824..ba583f3 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -5150,7 +5150,7 @@ void tst_QString::literals() QVERIFY(str.length() == 4); QVERIFY(str == QLatin1String("abcd")); QVERIFY(str.data_ptr()->ref.isStatic()); - QVERIFY(str.data_ptr()->offset == 0); + QVERIFY(str.data_ptr()->offset == sizeof(QStringData)); const QChar *s = str.constData(); QString str2 = str; -- 2.7.4