Skip to content
Snippets Groups Projects
Commit af4fcde1 authored by hjk's avatar hjk
Browse files

qstringlist: polishing

Make operator% only act on types we want to handle.
Also add a benchmark for comparison with QString::reserve();
parent da2c44ee
No related branches found
No related tags found
No related merge requests found
...@@ -80,14 +80,26 @@ public: ...@@ -80,14 +80,26 @@ public:
return s; return s;
} }
private: private:
const int m_size; const int m_size;
const char *m_data; 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; } inline int qStringBuilderSize(const char) { return 1; }
...@@ -101,10 +113,12 @@ inline int qStringBuilderSize(const QString &a) { return a.size(); } ...@@ -101,10 +113,12 @@ inline int qStringBuilderSize(const QString &a) { return a.size(); }
inline int qStringBuilderSize(const QStringRef &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> 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) inline void qStringBuilderAppend(const char c, QChar *&out)
{ {
...@@ -143,55 +157,46 @@ inline void qStringBuilderAppend(const QLatin1Literal &a, QChar *&out) ...@@ -143,55 +157,46 @@ inline void qStringBuilderAppend(const QLatin1Literal &a, QChar *&out)
} }
template <typename A, typename B> template <typename A, typename B>
inline void qStringBuilderAppend(const QStringBuilder<A, B> &p, QChar inline void qStringBuilderAppend(const QStringBuilder<A, B> &p, QChar *&out)
*&out);
template <typename A, typename B>
class QStringBuilder
{ {
public: qStringBuilderAppend(p.a, out);
QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {} qStringBuilderAppend(p.b, out);
}
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;
};
template <typename A, typename B> 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> template <typename A, typename B>
inline void qStringBuilderAppend(const QStringBuilder<A, B> &p, QChar *&out) struct QConcatenable< QStringBuilder<A, B> > { typedef QStringBuilder<A, B> type; };
{
qStringBuilderAppend(p.a, out);
qStringBuilderAppend(p.b, out);
}
} // Qt } // namespace
template <typename A, typename B> template <typename A, typename B>
Qt::QStringBuilder<A, B> QStringBuilder<A, B> operator%(const A &a, const B &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);
} }
......
...@@ -217,6 +217,48 @@ private slots: ...@@ -217,6 +217,48 @@ private slots:
QBENCHMARK { result = ba + ba + ba; } 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: private:
const QLatin1Literal l1literal; const QLatin1Literal l1literal;
const QLatin1String l1string; const QLatin1String l1string;
...@@ -229,8 +271,15 @@ private: ...@@ -229,8 +271,15 @@ private:
}; };
//void operator%(QString, int) {}
int main(int argc, char *argv[]) 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"))) { if (argc == 2 && (argv[1] == L("--run-builder") || argv[1] == L("-b"))) {
tst_qstringbuilder test; tst_qstringbuilder test;
return test.run_builder(); return test.run_builder();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment