From af4fcde1c2a17276f2d7b360c19a0493a78b4a0e Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Tue, 26 May 2009 15:52:53 +0200 Subject: [PATCH] qstringlist: polishing Make operator% only act on types we want to handle. Also add a benchmark for comparison with QString::reserve(); --- src/libs/utils/qstringbuilder.h | 87 +++++++++++++----------- tests/benchmarks/qstringbuilder/main.cpp | 49 +++++++++++++ 2 files changed, 95 insertions(+), 41 deletions(-) diff --git a/src/libs/utils/qstringbuilder.h b/src/libs/utils/qstringbuilder.h index ba3d452c5f9..7d2f166d711 100644 --- a/src/libs/utils/qstringbuilder.h +++ b/src/libs/utils/qstringbuilder.h @@ -80,14 +80,26 @@ public: return s; } - private: const int m_size; const char *m_data; }; -namespace Qt { +namespace { + +template <typename A, typename B> +class QStringBuilder +{ +public: + QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {} + operator QString() const; + +public: + const A &a; + const B &b; +}; + inline int qStringBuilderSize(const char) { return 1; } @@ -101,10 +113,12 @@ inline int qStringBuilderSize(const QString &a) { return a.size(); } inline int qStringBuilderSize(const QStringRef &a) { return a.size(); } -template <typename A, typename B> class QStringBuilder; - template <typename A, typename B> -inline int qStringBuilderSize(const QStringBuilder<A, B> &p); +inline int qStringBuilderSize(const QStringBuilder<A, B> &p) +{ + return qStringBuilderSize(p.a) + qStringBuilderSize(p.b); +} + inline void qStringBuilderAppend(const char c, QChar *&out) { @@ -143,55 +157,46 @@ inline void qStringBuilderAppend(const QLatin1Literal &a, QChar *&out) } template <typename A, typename B> -inline void qStringBuilderAppend(const QStringBuilder<A, B> &p, QChar -*&out); - -template <typename A, typename B> -class QStringBuilder +inline void qStringBuilderAppend(const QStringBuilder<A, B> &p, QChar *&out) { -public: - QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {} - - operator QString() const - { - #ifdef USE_CHANGED_QSTRING - QString s(this->size(), QChar(-1)); - #else - QString s; - s.resize(Qt::qStringBuilderSize(*this)); - #endif - QChar *d = s.data(); - Qt::qStringBuilderAppend(*this, d); - return s; - } - -public: - const A &a; - const B &b; -}; + qStringBuilderAppend(p.a, out); + qStringBuilderAppend(p.b, out); +} template <typename A, typename B> -inline int qStringBuilderSize(const QStringBuilder<A, B> &p) +QStringBuilder<A, B>::operator QString() const { - return qStringBuilderSize(p.a) + qStringBuilderSize(p.b); +#ifdef USE_CHANGED_QSTRING + QString s(this->size(), QChar(-1)); +#else + QString s; + s.resize(qStringBuilderSize(*this)); +#endif + QChar *d = s.data(); + qStringBuilderAppend(*this, d); + return s; } +// make sure the operator% defined below acts only on types we want to handle. +template <typename T> struct QConcatenable {}; +template <> struct QConcatenable<QString> { typedef QString type; }; +template <> struct QConcatenable<QLatin1String> { typedef QLatin1String type; }; +template <> struct QConcatenable<QLatin1Literal> { typedef QLatin1Literal type; }; +template <> struct QConcatenable<QLatin1Char> { typedef QLatin1Char type; }; +template <> struct QConcatenable<QStringRef> { typedef QStringRef type; }; template <typename A, typename B> -inline void qStringBuilderAppend(const QStringBuilder<A, B> &p, QChar *&out) -{ - qStringBuilderAppend(p.a, out); - qStringBuilderAppend(p.b, out); -} +struct QConcatenable< QStringBuilder<A, B> > { typedef QStringBuilder<A, B> type; }; -} // Qt +} // namespace template <typename A, typename B> -Qt::QStringBuilder<A, B> -operator%(const A &a, const B &b) +QStringBuilder<A, B> operator%(const A &a, const B &b) { - return Qt::QStringBuilder<A, B>(a, b); + typedef typename QConcatenable<A>::type A1; + typedef typename QConcatenable<B>::type B1; + return QStringBuilder<A1, B1>(a, b); } diff --git a/tests/benchmarks/qstringbuilder/main.cpp b/tests/benchmarks/qstringbuilder/main.cpp index b8f087346b3..6cecfba6b48 100644 --- a/tests/benchmarks/qstringbuilder/main.cpp +++ b/tests/benchmarks/qstringbuilder/main.cpp @@ -217,6 +217,48 @@ private slots: QBENCHMARK { result = ba + ba + ba; } } + + void separator_9() { SEP("QString::reserve()"); } + + void b_reserve() { + QBENCHMARK { + r.clear(); + r = string % string % string % string; + } + COMPARE(r, string + string + string + string); + } + void b_reserve_lit() { + QBENCHMARK { + r.clear(); + r = string % l1literal % string % string; + } + COMPARE(r, string + string + string + string); + } + void s_reserve() { + QBENCHMARK { + r.clear(); + r.reserve(string.size() + string.size() + string.size() + string.size()); + r += string; + r += string; + r += string; + r += string; + } + COMPARE(r, string + string + string + string); + } + void s_reserve_lit() { + QBENCHMARK { + r.clear(); + //r.reserve(string.size() + qstrlen(l1string.latin1()) + // + string.size() + string.size()); + r.reserve(1024); + r += string; + r += l1string; + r += string; + r += string; + } + COMPARE(r, string + string + string + string); + } + private: const QLatin1Literal l1literal; const QLatin1String l1string; @@ -229,8 +271,15 @@ private: }; +//void operator%(QString, int) {} + int main(int argc, char *argv[]) { + 42 % 3; // Sanity test, should always work. + + //QString("x") % 2; // Sanity test, should only compile when the + // operator%(QString, int) is visible. + if (argc == 2 && (argv[1] == L("--run-builder") || argv[1] == L("-b"))) { tst_qstringbuilder test; return test.run_builder(); -- GitLab