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 <thiago.macieira@intel.com>
This commit is contained in:
parent
3fe1eed053
commit
a5233b6b22
@ -94,6 +94,8 @@
|
|||||||
#define ULLONG_MAX quint64_C(18446744073709551615)
|
#define ULLONG_MAX quint64_C(18446744073709551615)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define IS_RAW_DATA(d) ((d)->offset != sizeof(QStringData))
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#ifndef QT_NO_TEXTCODEC
|
#ifndef QT_NO_TEXTCODEC
|
||||||
@ -800,8 +802,8 @@ const QString::Null QString::null = { };
|
|||||||
\sa split()
|
\sa split()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const QStaticStringData<1> QString::shared_null = { { 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, { 0 } }, { 0 } };
|
const QStaticStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, sizeof(QStringData) }, { 0 } };
|
||||||
|
|
||||||
int QString::grow(int size)
|
int QString::grow(int size)
|
||||||
{
|
{
|
||||||
@ -1052,7 +1054,7 @@ QString::QString(const QChar *unicode, int size)
|
|||||||
d->size = size;
|
d->size = size;
|
||||||
d->alloc = (uint) size;
|
d->alloc = (uint) size;
|
||||||
d->capacityReserved = false;
|
d->capacityReserved = false;
|
||||||
d->offset = 0;
|
d->offset = sizeof(QStringData);
|
||||||
memcpy(d->data(), unicode, size * sizeof(QChar));
|
memcpy(d->data(), unicode, size * sizeof(QChar));
|
||||||
d->data()[size] = '\0';
|
d->data()[size] = '\0';
|
||||||
}
|
}
|
||||||
@ -1076,7 +1078,7 @@ QString::QString(int size, QChar ch)
|
|||||||
d->size = size;
|
d->size = size;
|
||||||
d->alloc = (uint) size;
|
d->alloc = (uint) size;
|
||||||
d->capacityReserved = false;
|
d->capacityReserved = false;
|
||||||
d->offset = 0;
|
d->offset = sizeof(QStringData);
|
||||||
d->data()[size] = '\0';
|
d->data()[size] = '\0';
|
||||||
ushort *i = d->data() + size;
|
ushort *i = d->data() + size;
|
||||||
ushort *b = d->data();
|
ushort *b = d->data();
|
||||||
@ -1100,7 +1102,7 @@ QString::QString(int size, Qt::Initialization)
|
|||||||
d->size = size;
|
d->size = size;
|
||||||
d->alloc = (uint) size;
|
d->alloc = (uint) size;
|
||||||
d->capacityReserved = false;
|
d->capacityReserved = false;
|
||||||
d->offset = 0;
|
d->offset = sizeof(QStringData);
|
||||||
d->data()[size] = '\0';
|
d->data()[size] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,7 +1124,7 @@ QString::QString(QChar ch)
|
|||||||
d->size = 1;
|
d->size = 1;
|
||||||
d->alloc = 1;
|
d->alloc = 1;
|
||||||
d->capacityReserved = false;
|
d->capacityReserved = false;
|
||||||
d->offset = 0;
|
d->offset = sizeof(QStringData);
|
||||||
d->data()[0] = ch.unicode();
|
d->data()[0] = ch.unicode();
|
||||||
d->data()[1] = '\0';
|
d->data()[1] = '\0';
|
||||||
}
|
}
|
||||||
@ -1220,7 +1222,7 @@ void QString::resize(int size)
|
|||||||
if (size < 0)
|
if (size < 0)
|
||||||
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;
|
d->size = size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1294,14 +1296,14 @@ void QString::resize(int size)
|
|||||||
// ### Qt 5: rename reallocData() to avoid confusion. 197625
|
// ### Qt 5: rename reallocData() to avoid confusion. 197625
|
||||||
void QString::realloc(int alloc)
|
void QString::realloc(int alloc)
|
||||||
{
|
{
|
||||||
if (d->ref.isShared() || d->offset) {
|
if (d->ref.isShared() || IS_RAW_DATA(d)) {
|
||||||
Data *x = static_cast<Data *>(::malloc(sizeof(Data) + (alloc+1) * sizeof(QChar)));
|
Data *x = static_cast<Data *>(::malloc(sizeof(Data) + (alloc+1) * sizeof(QChar)));
|
||||||
Q_CHECK_PTR(x);
|
Q_CHECK_PTR(x);
|
||||||
x->ref.initializeOwned();
|
x->ref.initializeOwned();
|
||||||
x->size = qMin(alloc, d->size);
|
x->size = qMin(alloc, d->size);
|
||||||
x->alloc = (uint) alloc;
|
x->alloc = (uint) alloc;
|
||||||
x->capacityReserved = d->capacityReserved;
|
x->capacityReserved = d->capacityReserved;
|
||||||
x->offset =0;
|
x->offset = sizeof(QStringData);
|
||||||
::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
|
::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
|
||||||
x->data()[x->size] = 0;
|
x->data()[x->size] = 0;
|
||||||
if (!d->ref.deref())
|
if (!d->ref.deref())
|
||||||
@ -1312,7 +1314,7 @@ void QString::realloc(int alloc)
|
|||||||
Q_CHECK_PTR(p);
|
Q_CHECK_PTR(p);
|
||||||
d = p;
|
d = p;
|
||||||
d->alloc = alloc;
|
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->size = size;
|
||||||
d->alloc = (uint) size;
|
d->alloc = (uint) size;
|
||||||
d->capacityReserved = false;
|
d->capacityReserved = false;
|
||||||
d->offset = 0;
|
d->offset = sizeof(QStringData);
|
||||||
d->data()[size] = '\0';
|
d->data()[size] = '\0';
|
||||||
ushort *dst = d->data();
|
ushort *dst = d->data();
|
||||||
/* SIMD:
|
/* SIMD:
|
||||||
@ -4769,7 +4771,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
|
|||||||
|
|
||||||
const ushort *QString::utf16() const
|
const ushort *QString::utf16() const
|
||||||
{
|
{
|
||||||
if (d->offset)
|
if (IS_RAW_DATA(d))
|
||||||
const_cast<QString*>(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings
|
const_cast<QString*>(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings
|
||||||
return d->data();
|
return d->data();
|
||||||
}
|
}
|
||||||
@ -7050,7 +7052,7 @@ QString QString::fromRawData(const QChar *unicode, int size)
|
|||||||
x->size = size;
|
x->size = size;
|
||||||
x->alloc = 0;
|
x->alloc = 0;
|
||||||
x->capacityReserved = false;
|
x->capacityReserved = false;
|
||||||
x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort));
|
x->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(x);
|
||||||
}
|
}
|
||||||
return QString(x, 0);
|
return QString(x, 0);
|
||||||
}
|
}
|
||||||
@ -7076,9 +7078,9 @@ QString &QString::setRawData(const QChar *unicode, int size)
|
|||||||
} else {
|
} else {
|
||||||
if (unicode) {
|
if (unicode) {
|
||||||
d->size = size;
|
d->size = size;
|
||||||
d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort));
|
d->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(d);
|
||||||
} else {
|
} else {
|
||||||
d->offset = 0;
|
d->offset = sizeof(QStringData);
|
||||||
d->size = 0;
|
d->size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,12 +75,11 @@ struct QStringData {
|
|||||||
int size;
|
int size;
|
||||||
uint alloc : 31;
|
uint alloc : 31;
|
||||||
uint capacityReserved : 1;
|
uint capacityReserved : 1;
|
||||||
union {
|
|
||||||
qptrdiff offset; // will always work as we add/subtract from a ushort ptr
|
qptrdiff offset;
|
||||||
ushort d[sizeof(qptrdiff)/sizeof(ushort)];
|
|
||||||
};
|
inline ushort *data() { return reinterpret_cast<ushort *>(reinterpret_cast<char *>(this) + offset); }
|
||||||
inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
|
inline const ushort *data() const { return reinterpret_cast<const ushort *>(reinterpret_cast<const char *>(this) + offset); }
|
||||||
inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int N> struct QStaticStringData;
|
template<int N> struct QStaticStringData;
|
||||||
@ -126,7 +125,7 @@ template<int N> struct QStaticStringData
|
|||||||
# define QStringLiteral(str) ([]() -> QStaticStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
# define QStringLiteral(str) ([]() -> QStaticStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
||||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||||
static const QStaticStringData<Size> qstring_literal = \
|
static const QStaticStringData<Size> 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<Size> holder = { &qstring_literal }; \
|
QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||||
return holder; }())
|
return holder; }())
|
||||||
|
|
||||||
@ -139,7 +138,7 @@ template<int N> struct QStaticStringData
|
|||||||
__extension__ ({ \
|
__extension__ ({ \
|
||||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||||
static const QStaticStringData<Size> qstring_literal = \
|
static const QStaticStringData<Size> 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<Size> holder = { &qstring_literal }; \
|
QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||||
holder; })
|
holder; })
|
||||||
# endif
|
# endif
|
||||||
@ -705,7 +704,7 @@ inline QChar *QString::data()
|
|||||||
inline const QChar *QString::constData() const
|
inline const QChar *QString::constData() const
|
||||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||||
inline void QString::detach()
|
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
|
inline bool QString::isDetached() const
|
||||||
{ return !d->ref.isShared(); }
|
{ return !d->ref.isShared(); }
|
||||||
inline QString &QString::operator=(const QLatin1String &s)
|
inline QString &QString::operator=(const QLatin1String &s)
|
||||||
|
@ -5150,7 +5150,7 @@ void tst_QString::literals()
|
|||||||
QVERIFY(str.length() == 4);
|
QVERIFY(str.length() == 4);
|
||||||
QVERIFY(str == QLatin1String("abcd"));
|
QVERIFY(str == QLatin1String("abcd"));
|
||||||
QVERIFY(str.data_ptr()->ref.isStatic());
|
QVERIFY(str.data_ptr()->ref.isStatic());
|
||||||
QVERIFY(str.data_ptr()->offset == 0);
|
QVERIFY(str.data_ptr()->offset == sizeof(QStringData));
|
||||||
|
|
||||||
const QChar *s = str.constData();
|
const QChar *s = str.constData();
|
||||||
QString str2 = str;
|
QString str2 = str;
|
||||||
|
Loading…
Reference in New Issue
Block a user