aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhjk <qtc-committer@nokia.com>2009-05-26 15:52:53 +0200
committerhjk <qtc-committer@nokia.com>2009-05-26 15:54:22 +0200
commitaf4fcde1c2a17276f2d7b360c19a0493a78b4a0e (patch)
tree4b1088f016bc92f196a69bb21755111f8dcdd5b6
parentda2c44ee027569298724098995ef47298251de4d (diff)
qstringlist: polishing
Make operator% only act on types we want to handle. Also add a benchmark for comparison with QString::reserve();
-rw-r--r--src/libs/utils/qstringbuilder.h87
-rw-r--r--tests/benchmarks/qstringbuilder/main.cpp49
2 files changed, 95 insertions, 41 deletions
diff --git a/src/libs/utils/qstringbuilder.h b/src/libs/utils/qstringbuilder.h
index ba3d452c5f..7d2f166d71 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 b8f087346b..6cecfba6b4 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();