QString: where possible, re-use existing capacity in op(QChar/QL1S)

If the LHS is detached and has existing capacity that is large
enough to hold the RHS, re-use the memory instead of allocating
a new buffer and throwing away the old.

Change-Id: I53d42825da92c264c7301e8e771cba9fb35c321b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2015-10-11 15:01:06 +02:00
parent 2baeeb4026
commit 6de49f4ab6
3 changed files with 88 additions and 7 deletions

View File

@ -1818,6 +1818,17 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
Assigns the Latin-1 string \a str to this string.
*/
QString &QString::operator=(QLatin1String other)
{
if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
d->size = other.size();
d->data()[other.size()] = 0;
qt_from_latin1(d->data(), other.latin1(), other.size());
} else {
*this = fromLatin1(other.latin1(), other.size());
}
return *this;
}
/*! \fn QString &QString::operator=(const QByteArray &ba)
@ -1868,7 +1879,16 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
*/
QString &QString::operator=(QChar ch)
{
return operator=(QString(ch));
if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
// re-use existing capacity:
ushort *dat = d->data();
dat[0] = ch.unicode();
dat[1] = 0;
d->size = 1;
} else {
operator=(QString(ch));
}
return *this;
}
/*!

View File

@ -221,7 +221,7 @@ public:
inline ~QString();
QString &operator=(QChar c);
QString &operator=(const QString &) Q_DECL_NOTHROW;
inline QString &operator=(QLatin1String latin1);
QString &operator=(QLatin1String latin1);
#ifdef Q_COMPILER_RVALUE_REFS
inline QString(QString && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
inline QString &operator=(QString &&other) Q_DECL_NOTHROW
@ -884,11 +884,6 @@ inline void QString::detach()
{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) reallocData(uint(d->size) + 1u); }
inline bool QString::isDetached() const
{ return !d->ref.isShared(); }
inline QString &QString::operator=(QLatin1String s)
{
*this = fromLatin1(s.latin1(), s.size());
return *this;
}
inline void QString::clear()
{ if (!isNull()) *this = QString(); }
inline QString::QString(const QString &other) Q_DECL_NOTHROW : d(other.d)

View File

@ -582,6 +582,7 @@ private slots:
void compareQLatin1Strings();
void fromQLatin1StringWithLength();
void assignQLatin1String();
void assignQChar();
void isRightToLeft_data();
void isRightToLeft();
void unicodeStrings();
@ -6598,6 +6599,71 @@ void tst_QString::assignQLatin1String()
QCOMPARE(foo.size(), latin1subfoo.size());
QCOMPARE(foo, QString::fromLatin1("foo"));
// check capacity re-use:
QString s;
QCOMPARE(s.capacity(), 0);
// assign to null QString:
s = latin1foo;
QCOMPARE(s, QString::fromLatin1("foo"));
QCOMPARE(s.capacity(), 3);
// assign to non-null QString with enough capacity:
s = QString::fromLatin1("foofoo");
const int capacity = s.capacity();
s = latin1foo;
QCOMPARE(s, QString::fromLatin1("foo"));
QCOMPARE(s.capacity(), capacity);
// assign to shared QString (enough capacity, but can't use):
s = QString::fromLatin1("foofoo");
QString s2 = s;
s = latin1foo;
QCOMPARE(s, QString::fromLatin1("foo"));
QCOMPARE(s.capacity(), 3);
// assign to QString with too little capacity:
s = QString::fromLatin1("fo");
QCOMPARE(s.capacity(), 2);
s = latin1foo;
QCOMPARE(s, QString::fromLatin1("foo"));
QCOMPARE(s.capacity(), 3);
}
void tst_QString::assignQChar()
{
const QChar sp = QLatin1Char(' ');
QString s;
QCOMPARE(s.capacity(), 0);
// assign to null QString:
s = sp;
QCOMPARE(s, QString(sp));
QCOMPARE(s.capacity(), 1);
// assign to non-null QString with enough capacity:
s = QLatin1String("foo");
const int capacity = s.capacity();
QCOMPARE(capacity, 3);
s = sp;
QCOMPARE(s, QString(sp));
QCOMPARE(s.capacity(), capacity);
// assign to shared QString (enough capacity, but can't use):
s = QLatin1String("foo");
QString s2 = s;
s = sp;
QCOMPARE(s, QString(sp));
QCOMPARE(s.capacity(), 1);
// assign to empty QString:
s = QString("");
s.detach();
QCOMPARE(s.capacity(), 0);
s = sp;
QCOMPARE(s, QString(sp));
QCOMPARE(s.capacity(), 1);
}
void tst_QString::isRightToLeft_data()