qstringbuilder.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtCore module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
00039 **
00040 ****************************************************************************/
00041 
00042 #ifndef QSTRINGBUILDER_H
00043 #define QSTRINGBUILDER_H
00044 
00045 #include <QtCore/qstring.h>
00046 
00047 #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
00048 #  if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
00049 #    include <QtCore/qmap.h>
00050 #  endif
00051 #endif
00052 
00053 #include <string.h>
00054 
00055 QT_BEGIN_HEADER
00056 
00057 QT_BEGIN_NAMESPACE
00058 
00059 QT_MODULE(Core)
00060 
00061 // ### Qt 5: merge with QLatin1String
00062 class QLatin1Literal
00063 {
00064 public:
00065     int size() const { return m_size; }
00066     const char *data() const { return m_data; }
00067 
00068     template <int N>
00069     QLatin1Literal(const char (&str)[N])
00070         : m_size(N - 1), m_data(str) {}
00071 
00072 private:
00073     const int m_size;
00074     const char * const m_data;
00075 };
00076 
00077 struct Q_CORE_EXPORT QAbstractConcatenable
00078 {
00079 protected:
00080     static void convertFromAscii(const char *a, int len, QChar *&out);
00081 
00082     static inline void convertFromAscii(char a, QChar *&out)
00083     {
00084 #ifndef QT_NO_TEXTCODEC
00085         if (QString::codecForCStrings)
00086             *out++ = QChar::fromAscii(a);
00087         else
00088 #endif
00089             *out++ = QLatin1Char(a);
00090     }
00091 };
00092 
00093 template <typename T> struct QConcatenable {};
00094 
00095 template <typename A, typename B>
00096 class QStringBuilder
00097 {
00098 public:
00099     QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
00100 
00101     operator QString() const
00102     {
00103         const uint size = QConcatenable< QStringBuilder<A, B> >::size(*this);
00104         QString s(size, Qt::Uninitialized);
00105 
00106         QChar *d = s.data();
00107         const QChar * const start = d;
00108         QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
00109 
00110         if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(size) != d - start) {
00111             // this resize is necessary since we allocate a bit too much
00112             // when dealing with variable sized 8-bit encodings
00113             s.resize(d - start);
00114         }
00115         return s;
00116     }
00117     QByteArray toLatin1() const { return QString(*this).toLatin1(); }
00118 
00119     const A &a;
00120     const B &b;
00121 };
00122 
00123 template <>
00124 class QStringBuilder <QString, QString>
00125 {
00126     public:
00127         QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
00128 
00129         operator QString() const
00130         { QString r(a); r += b; return r; }
00131         QByteArray toLatin1() const { return QString(*this).toLatin1(); }
00132 
00133         const QString &a;
00134         const QString &b;
00135 };
00136 
00137 template <> struct QConcatenable<char> : private QAbstractConcatenable
00138 {
00139     typedef char type;
00140     enum { ExactSize = true };
00141     static int size(const char) { return 1; }
00142     static inline void appendTo(const char c, QChar *&out)
00143     {
00144         QAbstractConcatenable::convertFromAscii(c, out);
00145     }
00146 };
00147 
00148 template <> struct QConcatenable<QLatin1Char>
00149 {
00150     typedef QLatin1Char type;
00151     enum { ExactSize = true };
00152     static int size(const QLatin1Char) { return 1; }
00153     static inline void appendTo(const QLatin1Char c, QChar *&out)
00154     {
00155         *out++ = c;
00156     }
00157 };
00158 
00159 template <> struct QConcatenable<QChar>
00160 {
00161     typedef QChar type;
00162     enum { ExactSize = true };
00163     static int size(const QChar) { return 1; }
00164     static inline void appendTo(const QChar c, QChar *&out)
00165     {
00166         *out++ = c;
00167     }
00168 };
00169 
00170 template <> struct QConcatenable<QCharRef>
00171 {
00172     typedef QCharRef type;
00173     enum { ExactSize = true };
00174     static int size(const QCharRef &) { return 1; }
00175     static inline void appendTo(const QCharRef &c, QChar *&out)
00176     {
00177         *out++ = QChar(c);
00178     }
00179 };
00180 
00181 template <> struct QConcatenable<QLatin1String>
00182 {
00183     typedef QLatin1String type;
00184     enum { ExactSize = true };
00185     static int size(const QLatin1String &a) { return qstrlen(a.latin1()); }
00186     static inline void appendTo(const QLatin1String &a, QChar *&out)
00187     {
00188         for (const char *s = a.latin1(); *s; )
00189             *out++ = QLatin1Char(*s++);
00190     }
00191 
00192 };
00193 
00194 template <> struct QConcatenable<QLatin1Literal>
00195 {
00196     typedef QLatin1Literal type;
00197     enum { ExactSize = true };
00198     static int size(const QLatin1Literal &a) { return a.size(); }
00199     static inline void appendTo(const QLatin1Literal &a, QChar *&out)
00200     {
00201         for (const char *s = a.data(); *s; )
00202             *out++ = QLatin1Char(*s++);
00203     }
00204 };
00205 
00206 template <> struct QConcatenable<QString>
00207 {
00208     typedef QString type;
00209     enum { ExactSize = true };
00210     static int size(const QString &a) { return a.size(); }
00211     static inline void appendTo(const QString &a, QChar *&out)
00212     {
00213         const int n = a.size();
00214         memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
00215         out += n;
00216     }
00217 };
00218 
00219 template <> struct QConcatenable<QStringRef>
00220 {
00221     typedef QStringRef type;
00222     enum { ExactSize = true };
00223     static int size(const QStringRef &a) { return a.size(); }
00224     static inline void appendTo(QStringRef a, QChar *&out)
00225     {
00226         const int n = a.size();
00227         memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
00228         out += n;
00229     }
00230 };
00231 
00232 #ifndef QT_NO_CAST_FROM_ASCII
00233 template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
00234 {
00235     typedef char type[N];
00236     enum { ExactSize = false };
00237     static int size(const char[N])
00238     {
00239         return N - 1;
00240     }
00241     static inline void appendTo(const char a[N], QChar *&out)
00242     {
00243         QAbstractConcatenable::convertFromAscii(a, N, out);
00244     }
00245 };
00246 
00247 template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
00248 {
00249     typedef const char type[N];
00250     enum { ExactSize = false };
00251     static int size(const char[N]) { return N - 1; }
00252     static inline void appendTo(const char a[N], QChar *&out)
00253     {
00254         QAbstractConcatenable::convertFromAscii(a, N, out);
00255     }
00256 };
00257 
00258 template <> struct QConcatenable<const char *> : private QAbstractConcatenable
00259 {
00260     typedef char const *type;
00261     enum { ExactSize = false };
00262     static int size(const char *a) { return qstrlen(a); }
00263     static inline void appendTo(const char *a, QChar *&out)
00264     {
00265         QAbstractConcatenable::convertFromAscii(a, -1, out);
00266     }
00267 };
00268 
00269 template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
00270 {
00271     typedef QByteArray type;
00272     enum { ExactSize = false };
00273     static int size(const QByteArray &ba) { return qstrnlen(ba.constData(), ba.size()); }
00274     static inline void appendTo(const QByteArray &ba, QChar *&out)
00275     {
00276         QAbstractConcatenable::convertFromAscii(ba.constData(), -1, out);
00277     }
00278 };
00279 #endif
00280 
00281 template <typename A, typename B>
00282 struct QConcatenable< QStringBuilder<A, B> >
00283 {
00284     typedef QStringBuilder<A, B> type;
00285     enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize };
00286     static int size(const type &p)
00287     {
00288         return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
00289     }
00290     static inline void appendTo(const QStringBuilder<A, B> &p, QChar *&out)
00291     {
00292         QConcatenable<A>::appendTo(p.a, out);
00293         QConcatenable<B>::appendTo(p.b, out);
00294     }
00295 };
00296 
00297 template <typename A, typename B>
00298 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
00299 operator%(const A &a, const B &b)
00300 {
00301    return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
00302 }
00303 
00304 #ifdef QT_USE_FAST_OPERATOR_PLUS
00305 template <typename A, typename B>
00306 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
00307 operator+(const A &a, const B &b)
00308 {
00309    return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
00310 }
00311 #endif
00312 
00313 QT_END_NAMESPACE
00314 
00315 QT_END_HEADER
00316 
00317 #endif // QSTRINGBUILDER_H