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