From 0a4f6af142c57929bd743f3e95e25ada8642e9e4 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 6 Apr 2011 13:01:48 +0200 Subject: QStringBuilder: add operator += for QString and QByteArray Optimize cases when we have. string += someString + someOtherString Avoid the allocation of one temporary string. Behaviour change: byteArray += someString + QByteArray("foo\0bar", 7) before, the array would end at foo because of the conversion to string Reviewed-by: hjk --- src/corelib/tools/qstring.h | 3 +++ src/corelib/tools/qstringbuilder.h | 29 ++++++++++++++++++++++++ tests/auto/qstringbuilder1/stringbuilder.cpp | 33 ++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index b54258f..002e516 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -485,6 +485,9 @@ public: const_iterator constEnd() const; // STL compatibility + typedef const QChar & const_reference; + typedef QChar & reference; + typedef QChar value_type; inline void push_back(QChar c) { append(c); } inline void push_back(const QString &s) { append(s); } inline void push_front(QChar c) { prepend(c); } diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 260b574..2d3475f 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -419,6 +419,35 @@ operator+(const A &a, const B &b) } #endif +template +QByteArray &operator+=(QByteArray &a, const QStringBuilder &b) +{ +#ifndef QT_NO_CAST_TO_ASCII + if (sizeof(typename QConcatenable< QStringBuilder >::ConvertTo::value_type) == sizeof(QChar)) { + //it is not save to optimize as in utf8 it is not possible to compute the size + return a += QString(b); + } +#endif + int len = a.size() + QConcatenable< QStringBuilder >::size(b); + a.reserve(len); + char *it = a.data() + a.size(); + QConcatenable< QStringBuilder >::appendTo(b, it); + a.resize(len); //we need to resize after the appendTo for the case str+=foo+str + return a; +} + +template +QString &operator+=(QString &a, const QStringBuilder &b) +{ + int len = a.size() + QConcatenable< QStringBuilder >::size(b); + a.reserve(len); + QChar *it = a.data() + a.size(); + QConcatenable< QStringBuilder >::appendTo(b, it); + a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8 + return a; +} + + QT_END_NAMESPACE QT_END_HEADER diff --git a/tests/auto/qstringbuilder1/stringbuilder.cpp b/tests/auto/qstringbuilder1/stringbuilder.cpp index 3c8ddc2..035a1f4 100644 --- a/tests/auto/qstringbuilder1/stringbuilder.cpp +++ b/tests/auto/qstringbuilder1/stringbuilder.cpp @@ -163,4 +163,37 @@ void runScenario() QCOMPARE(r, r2); } + //operator QString += + { + QString str = QString::fromUtf8(UTF8_LITERAL); + str += QLatin1String(LITERAL) P str; + QCOMPARE(str, QString::fromUtf8(UTF8_LITERAL LITERAL UTF8_LITERAL)); +#ifndef QT_NO_CAST_FROM_ASCII + str = (QString::fromUtf8(UTF8_LITERAL) += QLatin1String(LITERAL) P UTF8_LITERAL); + QCOMPARE(str, QString::fromUtf8(UTF8_LITERAL LITERAL UTF8_LITERAL)); +#endif + } + + //operator QByteArray += + { + QByteArray ba = UTF8_LITERAL; + ba += QByteArray(LITERAL) P UTF8_LITERAL; + QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL)); + ba += LITERAL P QByteArray::fromRawData(UTF8_LITERAL_EXTRA, UTF8_LITERAL_LEN); + QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL LITERAL UTF8_LITERAL)); + QByteArray withZero = QByteArray(LITERAL "\0" LITERAL, LITERAL_LEN*2+1); + QByteArray ba2 = withZero; + ba2 += ba2 P withZero; + QCOMPARE(ba2, QByteArray(withZero + withZero + withZero)); +#ifndef QT_NO_CAST_TO_ASCII + ba = UTF8_LITERAL; + ba2 = (ba += QLatin1String(LITERAL) + QString::fromUtf8(UTF8_LITERAL)); + QCOMPARE(ba2, ba); + QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL)); + ba = UTF8_LITERAL; + ba += QLatin1String(LITERAL) P withZero; + QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL + withZero)); +#endif + } + } -- cgit v0.12