|
|
|
#include <QtTest/QtTest> |
|
#include <QStringBuilder> |
|
|
|
class bm_stringBuilder : public QObject |
|
{ |
|
Q_OBJECT |
|
public: |
|
bm_stringBuilder() {} |
|
|
|
private slots: |
|
void stringBuilder_data() |
|
{ |
|
int i = 0; |
|
QTest::addColumn<int>("testType"); |
|
QTest::newRow("QString.arg.arg") << i++; |
|
QTest::newRow("QString.arg") << i++; |
|
QTest::newRow("QStringLiteral.arg") << i++; |
|
QTest::newRow("QLatin1String.arg") << i++; |
|
QTest::newRow("QStringView.arg") << i++; |
|
QTest::newRow("QString.append") << i++; |
|
QTest::newRow("QStringLiteral.append") << i++; |
|
QTest::newRow("QByteArray.append") << i++; |
|
QTest::newRow("QByteArrayLiteral.append") << i++; |
|
QTest::newRow("QString.asprinf") << i++; |
|
QTest::newRow("QStringBuilder") << i++; |
|
QTest::newRow("QTextStream") << i++; |
|
} |
|
|
|
void stringBuilder() |
|
{ |
|
QString result; |
|
const QString expected("Type: %1; strVal1=This is a test; strVal2=a literal string; intVal1=255 (0x00ff);"); |
|
// some constants for replacing/appending in all tests |
|
const QLatin1String strVal1("This is a test"); |
|
const QLatin1String strVal2("a literal string"); |
|
const int intVal1 = 255; |
|
|
|
QFETCH(int, testType); |
|
switch (testType) { |
|
case 0: // QString.arg().arg()... (multi-arg) |
|
QBENCHMARK { |
|
result = QString("Type: %1; strVal1=%2; strVal2=%3; intVal1=%4 (0x%5);") |
|
.arg(testType) |
|
.arg(strVal1, strVal2) |
|
.arg(intVal1) |
|
.arg(intVal1, 4, 16, QChar('0')); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 1: // QString.arg() |
|
// The verbose QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0')) is faster |
|
// than arg(intVal1, 4, 16, QChar('0')), even if it's the only replacement argument |
|
// in the string (QString("%1").arg(...)). |
|
QBENCHMARK { |
|
result = QString("Type: %1; strVal1=%2; strVal2=%3; intVal1=%4 (0x%5);") |
|
.arg(QString::number(testType), strVal1, strVal2, QString::number(intVal1), |
|
QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0'))); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 2: // QStringLiteral.arg() |
|
QBENCHMARK { |
|
result = QStringLiteral("Type: %1; strVal1=%2; strVal2=%3; intVal1=%4 (0x%5);") |
|
.arg(QString::number(testType), strVal1, strVal2, QString::number(intVal1), |
|
QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0'))); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 3: // QLatin1String.arg() |
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) |
|
QBENCHMARK { |
|
result = QLatin1String("Type: %1; strVal1=%2; strVal2=%3; intVal1=%4 (0x%5);") |
|
.arg(QString::number(testType), strVal1, strVal2, QString::number(intVal1), |
|
QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0'))); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
#else |
|
QSKIP("Test requires newer Qt version"); |
|
#endif |
|
break; |
|
|
|
case 4: // QStringView.arg() |
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) |
|
{ |
|
const QString temp = QStringLiteral("Type: %1; strVal1=%2; strVal2=%3; intVal1=%4 (0x%5);"); |
|
QBENCHMARK { |
|
result = QStringView(temp) |
|
.arg(QString::number(testType), strVal1, strVal2, QString::number(intVal1), |
|
QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0'))); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
} |
|
#else |
|
QSKIP("Test requires newer Qt version"); |
|
#endif |
|
break; |
|
|
|
case 5: // QString.append() |
|
// QString.append(QLatin1String("foo")) is faster than append("foo") |
|
// and same as, or a very tiny bit slower than, append(QStringLiteral("foo")) |
|
QBENCHMARK { |
|
result = QString("Type: ").append(QString::number(testType)) |
|
.append(QLatin1String("; strVal1=")).append(strVal1) |
|
.append(QLatin1String("; strVal2=")).append(strVal2) |
|
.append(QLatin1String("; intVal1=")).append(QString::number(intVal1)) |
|
.append(QLatin1String(" (0x")) |
|
.append(QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0'))) |
|
.append(QLatin1String(");")); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 6: // QStringLiteral.append() |
|
// Here also append(QStringLiteral("foo")) is same as, or a very tiny bit |
|
// faster than, append(QLatin1String("foo")) |
|
QBENCHMARK { |
|
result = QStringLiteral("Type: ").append(QString::number(testType)) |
|
.append(QStringLiteral("; strVal1=")).append(strVal1) |
|
.append(QStringLiteral("; strVal2=")).append(strVal2) |
|
.append(QStringLiteral("; intVal1=")).append(QString::number(intVal1)) |
|
.append(QStringLiteral(" (0x")) |
|
.append(QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0'))) |
|
.append(QStringLiteral(");")); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 7: // QByteArray.append() |
|
QBENCHMARK { |
|
// QByteArray.append("foo") is faster than QByteArray.append(QLatin1String("foo")) |
|
// and about the same as QByteArray.append(QByteArrayLiteral("foo")) |
|
result = QByteArray("Type: ").append(QByteArray::number(testType)) |
|
.append("; strVal1=").append(strVal1) |
|
.append("; strVal2=").append(strVal2) |
|
.append("; intVal1=").append(QByteArray::number(intVal1)) |
|
.append(" (0x").append(QByteArray::number(intVal1, 16).rightJustified(4, '0')) |
|
.append(");"); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 8: // QByteArrayLiteral.append() |
|
// Here also append("foo") is faster than append(QLatin1String("foo")) |
|
// and about the same as append(QByteArrayLiteral("foo")) |
|
QBENCHMARK { |
|
result = QByteArrayLiteral("Type: ").append(QByteArray::number(testType)) |
|
.append(("; strVal1=")).append(strVal1) |
|
.append(("; strVal2=")).append(strVal2) |
|
.append(("; intVal1=")).append(QByteArray::number(intVal1)) |
|
.append((" (0x")).append(QByteArray::number(intVal1, 16).rightJustified(4, '0')) |
|
.append((");")); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 9: // QString.asprinf() |
|
QBENCHMARK { |
|
result = QString::asprintf("Type: %d; strVal1=%s; strVal2=%s; intVal1=%d (0x%04x);", |
|
testType, strVal1.data(), strVal2.data(), intVal1, intVal1); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 10: // QStringBuilder |
|
// No difference using "+" with QT_USE_QSTRINGBUILDER defined vs. |
|
// using "%" with #include <QStringBuilder>. |
|
// OTOH using "+" w/out QT_USE_QSTRINGBUILDER is almost as slow as the multi- .arg() tests. |
|
// QString::number() is faster here than QByteArray::number() |
|
QBENCHMARK { |
|
result = "Type: " + QString::number(testType) |
|
+ "; strVal1=" + strVal1 |
|
+ "; strVal2=" + strVal2 |
|
+ "; intVal1=" + QString::number(intVal1) |
|
+ " (0x" + QString::number(intVal1, 16).rightJustified(4, QLatin1Char('0')) |
|
+ ");"; |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
case 11: // QTextStream |
|
// stream << QLatin1String("foo") is faster than stream << "foo" |
|
QBENCHMARK { |
|
result = QString(); |
|
QTextStream out(&result, QIODevice::WriteOnly); |
|
out << QLatin1String("Type: ") << testType |
|
<< QLatin1String("; strVal1=") << strVal1 |
|
<< QLatin1String("; strVal2=") << strVal2 |
|
<< QLatin1String("; intVal1=") << intVal1 |
|
<< QLatin1String(" (0x") << hex << right |
|
<< qSetFieldWidth(4) << qSetPadChar(QLatin1Char('0')) << intVal1 |
|
<< qSetFieldWidth(0) << QLatin1String(");"); |
|
} |
|
QCOMPARE(result, expected.arg(testType)); |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
|
|
}; |
|
|
|
QTEST_MAIN(bm_stringBuilder) |
|
#include "bm_stringBuilder.moc" |