Commit d472ec9a authored by hjk's avatar hjk

remove qstringbuilder code

Now in Qt proper.
parent 27f9d972
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the $MODULE$ of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qstringbuilder.h"
/*!
\class QLatin1Literal
\reentrant
\brief The QLatin1Literal class provides a thin wrapper of string literal
used in source codes.
The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder
to reduce the number of reallocations needed to build up a string from
smaller chunks.
Contrary to \c QLatin1String, a \c QLatin1Literal can retrieve its size
without iterating over the literal.
\ingroup tools
\ingroup shared
\ingroup text
\mainclass
\sa QStringBuilder, QLatin1String, QString
*/
/*! \fn QLatin1Literal::QLatin1Literal(const char(&literal)[])
The only constructor of the class.
*/
/*! \fn int QLatin1Literal::size() const
Returns the number of characters in the literal \i{not} including
the trailing NUL char.
*/
/*! \fn char *QLatin1Literal::size() const
Returns a pointer to the first character of the string literal.
The string literal is terminated by a NUL character.
*/
/*! \fn QLatin1Literal::operator QString() const
Converts the \c QLatin1Literal into a \c QString object.
*/
/*!
\class QStringBuilderPair
\reentrant
\brief QStringBuilderPair is a helper class template for building
QStringBuilder objects wrapping two smaller QStringBuilder object.
*/
/*!
\class QStringBuilder
\reentrant
\brief QStringBuilder is a template class providing a facility to build
up QStrings from smaller chunks.
\ingroup tools
\ingroup shared
\ingroup text
\mainclass
When creating strings from smaller chunks, typically \c QString::operator+()
is used, resulting \i{n - 1} reallocations when operating on \i{n} chunks.
QStringBuilder uses expression
templates to collect the individual parts, compute the total size,
allocate memory for the resulting QString object, and copy the contents
of the chunks into the result.
Using \c QStringBuilder::operator%() yield generally better performance then
using \c QString::operator+() on the same chunks if there are three or
more of them, and equal performance otherwise.
\sa QLatin1Literal, QString
*/
/* !fn template <class A, class B> QStringBuilder< QStringBuilderPair<A, B> > operator%(const A &a, const B &b)
Creates a helper object containing both parameters.
This is the main function to build up complex QStringBuilder objects from
smaller QStringBuilder objects.
*/
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the $MODULE$ of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSTRINGBUILDER_H
#define QSTRINGBUILDER_H
#include <QtCore/qstring.h>
#include <string.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Core)
class QLatin1Literal
{
public:
template <int N>
QLatin1Literal(const char (&str)[N]) : m_size(N - 1), m_data(str) {}
inline int size() const { return m_size; }
inline const char *data() const { return m_data; }
private:
const int m_size;
const char *m_data;
};
namespace {
template <typename T> class QConcatenable {};
template <typename A, typename B>
class QStringBuilder
{
public:
QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
operator QString() const
{
#if 0
QString s(QConcatenable< QStringBuilder<A, B> >::size(*this),
QString::Uninitialized());
#else
QString s;
s.resize(QConcatenable< QStringBuilder<A, B> >::size(*this));
#endif
QChar *d = s.data();
QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
return s;
}
const A &a;
const B &b;
};
template <> struct QConcatenable<char>
{
typedef char type;
static int size(const char) { return 1; }
static inline void appendTo(const char c, QChar *&out)
{
*out++ = QLatin1Char(c);
}
};
template <> struct QConcatenable<QLatin1Char>
{
typedef QLatin1Char type;
static int size(const QLatin1Char) { return 1; }
static inline void appendTo(const QLatin1Char c, QChar *&out)
{
*out++ = c;
}
};
template <> struct QConcatenable<QLatin1String>
{
typedef QLatin1String type;
static int size(const QLatin1String &a) { return qstrlen(a.latin1()); }
static inline void appendTo(const QLatin1String &a, QChar *&out)
{
for (const char *s = a.latin1(); *s; )
*out++ = QLatin1Char(*s++);
}
};
template <> struct QConcatenable<QLatin1Literal>
{
typedef QLatin1Literal type;
static int size(const QLatin1Literal &a) { return a.size(); }
static inline void appendTo(const QLatin1Literal &a, QChar *&out)
{
for (const char *s = a.data(); *s; )
*out++ = QLatin1Char(*s++);
}
};
template <> struct QConcatenable<QString>
{
typedef QString type;
static int size(const QString &a) { return a.size(); }
static inline void appendTo(const QString &a, QChar *&out)
{
const int n = a.size();
memcpy(out, (char*)a.constData(), sizeof(QChar) * n);
out += n;
}
};
template <> struct QConcatenable<QStringRef>
{
typedef QStringRef type;
static int size(const QStringRef &a) { return a.size(); }
static inline void appendTo(QStringRef a, QChar *&out)
{
const int n = a.size();
memcpy(out, (char*)a.constData(), sizeof(QChar) * n);
out += n;
}
};
template <typename A, typename B>
struct QConcatenable< QStringBuilder<A, B> >
{
typedef QStringBuilder<A, B> type;
static int size(const type &p)
{
return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
}
static inline void appendTo(const QStringBuilder<A, B> &p, QChar *&out)
{
QConcatenable<A>::appendTo(p.a, out);
QConcatenable<B>::appendTo(p.b, out);
}
};
} // namespace
template <typename A, typename B>
QStringBuilder<A, B> operator%(const A &a, const B &b)
{
typedef typename QConcatenable<A>::type A1;
typedef typename QConcatenable<B>::type B1;
return QStringBuilder<A1, B1>(a, b);
}
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSTRINGBUILDER_H
#include "qstringbuilder.h"
#include <QDebug>
#include <QString>
#include <qtest.h>
#define COMPARE(a, b) QCOMPARE(a, b)
//#define COMPARE(a, b)
#define SEP(s) qDebug() << "\n\n-------- " s " ---------";
#define L(s) QLatin1String(s)
class tst_qstringbuilder : public QObject
{
Q_OBJECT
public:
tst_qstringbuilder()
: l1literal("some string literal"),
l1string("some string literal"),
ba("some string literal"),
string(l1string),
stringref(&string, 2, 10),
achar('c')
{}
public:
enum { N = 10000 };
int run_traditional()
{
int s = 0;
for (int i = 0; i < N; ++i) {
#if 0
s += QString(l1string + l1string).size();
s += QString(l1string + l1string + l1string).size();
s += QString(l1string + l1string + l1string + l1string).size();
s += QString(l1string + l1string + l1string + l1string + l1string).size();
#endif
s += QString(achar + l1string + achar).size();
}
return s;
}
int run_builder()
{
int s = 0;
for (int i = 0; i < N; ++i) {
#if 0
s += QString(l1literal % l1literal).size();
s += QString(l1literal % l1literal % l1literal).size();
s += QString(l1literal % l1literal % l1literal % l1literal).size();
s += QString(l1literal % l1literal % l1literal % l1literal % l1literal).size();
#endif
s += QString(achar % l1literal % achar).size();
}
return s;
}
private slots:
void separator_0() {
qDebug() << "\nIn each block the QStringBuilder based result appear first, "
"QStringBased second.\n";
}
void separator_1() { SEP("literal + literal (builder first)"); }
void b_2_l1literal() {
QBENCHMARK { r = l1literal % l1literal; }
COMPARE(r, l1string + l1string);
}
void s_2_l1string() {
QBENCHMARK { r = l1string + l1string; }
COMPARE(r, QString(l1literal % l1literal));
}
void separator_2() { SEP("2 strings"); }
void b_2_string() {
QBENCHMARK { r = string % string; }
COMPARE(r, string + string);
}
void s_2_string() {
QBENCHMARK { r = string + string; }
COMPARE(r, QString(string % string));
}
void separator_2c() { SEP("2 string refs"); }
void b_2_stringref() {
QBENCHMARK { r = stringref % stringref; }
COMPARE(r, stringref.toString() + stringref.toString());
}
void s_2_stringref() {
QBENCHMARK { r = stringref.toString() + stringref.toString(); }
COMPARE(r, QString(stringref % stringref));
}
void separator_2b() { SEP("3 strings"); }
void b_3_string() {
QBENCHMARK { r = string % string % string; }
COMPARE(r, string + string + string);
}
void s_3_string() {
QBENCHMARK { r = string + string + string; }
COMPARE(r, QString(string % string % string));
}
void separator_2a() { SEP("string + literal (builder first)"); }
void b_string_l1literal() {
QBENCHMARK { r = string % l1literal; }
COMPARE(r, string + l1string);
}
void b_string_l1string() {
QBENCHMARK { r = string % l1string; }
COMPARE(r, string + l1string);
}
void s_string_l1literal() {
QBENCHMARK { r = string + l1string; }
COMPARE(r, QString(string % l1literal));
}
void s_string_l1string() {
QBENCHMARK { r = string + l1string; }
COMPARE(r, QString(string % l1literal));
}
void separator_3() { SEP("3 literals"); }
void b_3_l1literal() {
QBENCHMARK { r = l1literal % l1literal % l1literal; }
COMPARE(r, l1string + l1string + l1string);
}
void s_3_l1string() {
QBENCHMARK { r = l1string + l1string + l1string; }
COMPARE(r, QString(l1literal % l1literal % l1literal));
}
void separator_4() { SEP("4 literals"); }
void b_4_l1literal() {
QBENCHMARK { r = l1literal % l1literal % l1literal % l1literal; }
COMPARE(r, l1string + l1string + l1string + l1string);
}
void s_4_l1string() {
QBENCHMARK { r = l1string + l1string + l1string + l1string; }
COMPARE(r, QString(l1literal % l1literal % l1literal % l1literal));
}
void separator_5() { SEP("5 literals"); }
void b_5_l1literal() {
QBENCHMARK { r = l1literal % l1literal % l1literal % l1literal %l1literal; }
COMPARE(r, l1string + l1string + l1string + l1string + l1string);
}
void s_5_l1string() {
QBENCHMARK { r = l1string + l1string + l1string + l1string + l1string; }
COMPARE(r, QString(l1literal % l1literal % l1literal % l1literal % l1literal));
}
void separator_6() { SEP("4 chars"); }
void b_string_4_char() {
QBENCHMARK { r = string + achar + achar + achar + achar; }
COMPARE(r, QString(string % achar % achar % achar % achar));
}
void s_string_4_char() {
QBENCHMARK { r = string + achar + achar + achar + achar; }
COMPARE(r, QString(string % achar % achar % achar % achar));
}
void separator_7() { SEP("char + string + char"); }
void b_char_string_char() {
QBENCHMARK { r = achar + string + achar; }
COMPARE(r, QString(achar % string % achar));
}
void s_char_string_char() {
QBENCHMARK { r = achar + string + achar; }
COMPARE(r, QString(achar % string % achar));
}
void separator_8() { SEP("string.arg"); }
void b_string_arg() {
const QString pattern = l1string + "%1" + l1string;
QBENCHMARK { r = l1literal % string % l1literal; }
COMPARE(r, l1string + string + l1string);
}
void s_string_arg() {
const QString pattern = l1string + "%1" + l1string;
QBENCHMARK { r = pattern.arg(string); }
COMPARE(r, l1string + string + l1string);
}
void s_bytearray_arg() {
QByteArray result;
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;
const QByteArray ba;
const QString string;
const QStringRef stringref;
const QLatin1Char achar;
QString r;
};
//void operator%(QString, int) {}
int main(int argc, char *argv[])
{
//qDebug() << (QString("xx") * QLatin1String("y")).toString();
//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();
}
if (argc == 2 && (argv[1] == L("--run-traditional") || argv[1] == L("-t"))) {
tst_qstringbuilder test;
return test.run_traditional();
}
if (argc == 1) {
QCoreApplication app(argc, argv);
QStringList args = app.arguments();
tst_qstringbuilder test;
return QTest::qExec(&test, argc, argv);
}
qDebug() << "Usage: " << argv[0] << " [--run-builder|-r|--run-traditional|-t]";
}
#include "main.moc"