1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QSTRINGBUILDER_H
43 #define QSTRINGBUILDER_H
45 #include <QtCore/qstring.h>
46 #include <QtCore/qbytearray.h>
48 #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
49 # if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
50 # include <QtCore/qmap.h>
61 struct Q_CORE_EXPORT QAbstractConcatenable
64 static void convertFromAscii(const char *a, int len, QChar *&out);
65 static inline void convertFromAscii(char a, QChar *&out)
67 *out++ = QLatin1Char(a);
71 template <typename T> struct QConcatenable {};
73 template <typename A, typename B>
77 QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
79 friend class QByteArray;
81 template <typename T> T convertTo() const
83 const uint len = QConcatenable< QStringBuilder<A, B> >::size(*this);
84 T s(len, Qt::Uninitialized);
86 typename T::iterator d = s.data();
87 typename T::const_iterator const start = d;
88 QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
90 if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(len) != d - start) {
91 // this resize is necessary since we allocate a bit too much
92 // when dealing with variable sized 8-bit encodings
98 typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
99 typedef typename Concatenable::ConvertTo ConvertTo;
101 operator ConvertTo() const { return convertTo<ConvertTo>(); }
103 QByteArray toLatin1() const { return convertTo<QString>().toLatin1(); }
104 int size() const { return Concatenable::size(*this); }
111 class QStringBuilder <QString, QString>
114 QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
116 operator QString() const
117 { QString r(a); r += b; return r; }
118 QByteArray toLatin1() const { return QString(*this).toLatin1(); }
125 class QStringBuilder <QByteArray, QByteArray>
128 QStringBuilder(const QByteArray &a_, const QByteArray &b_) : a(a_), b(b_) {}
130 operator QByteArray() const
131 { QByteArray r(a); r += b; return r; }
138 template <> struct QConcatenable<char> : private QAbstractConcatenable
141 typedef QByteArray ConvertTo;
142 enum { ExactSize = true };
143 static int size(const char) { return 1; }
144 #ifndef QT_NO_CAST_FROM_ASCII
145 static inline QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
147 QAbstractConcatenable::convertFromAscii(c, out);
150 static inline void appendTo(const char c, char *&out)
154 template <> struct QConcatenable<QLatin1Char>
156 typedef QLatin1Char type;
157 typedef QString ConvertTo;
158 enum { ExactSize = true };
159 static int size(const QLatin1Char) { return 1; }
160 static inline void appendTo(const QLatin1Char c, QChar *&out)
162 static inline void appendTo(const QLatin1Char c, char *&out)
163 { *out++ = c.toLatin1(); }
166 template <> struct QConcatenable<QChar> : private QAbstractConcatenable
169 typedef QString ConvertTo;
170 enum { ExactSize = true };
171 static int size(const QChar) { return 1; }
172 static inline void appendTo(const QChar c, QChar *&out)
176 template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
178 typedef QCharRef type;
179 typedef QString ConvertTo;
180 enum { ExactSize = true };
181 static int size(const QCharRef &) { return 1; }
182 static inline void appendTo(const QCharRef &c, QChar *&out)
183 { *out++ = QChar(c); }
186 template <> struct QConcatenable<QLatin1String>
188 typedef QLatin1String type;
189 typedef QString ConvertTo;
190 enum { ExactSize = true };
191 static int size(const QLatin1String &a) { return a.size(); }
192 static inline void appendTo(const QLatin1String &a, QChar *&out)
194 for (const char *s = a.data(); *s; )
195 *out++ = QLatin1Char(*s++);
197 static inline void appendTo(const QLatin1String &a, char *&out)
199 for (const char *s = a.data(); *s; )
204 template <> struct QConcatenable<QString> : private QAbstractConcatenable
206 typedef QString type;
207 typedef QString ConvertTo;
208 enum { ExactSize = true };
209 static int size(const QString &a) { return a.size(); }
210 static inline void appendTo(const QString &a, QChar *&out)
212 const int n = a.size();
213 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
218 template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
220 typedef QConstStringDataPtr<N> type;
221 typedef QString ConvertTo;
222 enum { ExactSize = true };
223 static int size(const type &) { return N; }
224 static inline void appendTo(const type &a, QChar *&out)
226 memcpy(out, reinterpret_cast<const char*>(a.ptr->data), sizeof(QChar) * N);
231 template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
233 typedef QStringRef type;
234 typedef QString ConvertTo;
235 enum { ExactSize = true };
236 static int size(const QStringRef &a) { return a.size(); }
237 static inline void appendTo(const QStringRef &a, QChar *&out)
239 const int n = a.size();
240 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
245 template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
247 typedef char type[N];
248 typedef QByteArray ConvertTo;
249 enum { ExactSize = false };
250 static int size(const char[N]) { return N - 1; }
251 #ifndef QT_NO_CAST_FROM_ASCII
252 static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
254 QAbstractConcatenable::convertFromAscii(a, N - 1, out);
257 static inline void appendTo(const char a[N], char *&out)
264 template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
266 typedef const char type[N];
267 typedef QByteArray ConvertTo;
268 enum { ExactSize = false };
269 static int size(const char[N]) { return N - 1; }
270 #ifndef QT_NO_CAST_FROM_ASCII
271 static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
273 QAbstractConcatenable::convertFromAscii(a, N - 1, out);
276 static inline void appendTo(const char a[N], char *&out)
283 template <> struct QConcatenable<const char *> : private QAbstractConcatenable
285 typedef char const *type;
286 typedef QByteArray ConvertTo;
287 enum { ExactSize = false };
288 static int size(const char *a) { return qstrlen(a); }
289 #ifndef QT_NO_CAST_FROM_ASCII
290 static inline void QT_ASCII_CAST_WARN appendTo(const char *a, QChar *&out)
291 { QAbstractConcatenable::convertFromAscii(a, -1, out); }
293 static inline void appendTo(const char *a, char *&out)
302 template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
304 typedef QByteArray type;
305 typedef QByteArray ConvertTo;
306 enum { ExactSize = false };
307 static int size(const QByteArray &ba) { return ba.size(); }
308 #ifndef QT_NO_CAST_FROM_ASCII
309 static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
311 QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
314 static inline void appendTo(const QByteArray &ba, char *&out)
316 const char *a = ba.constData();
317 const char * const end = ba.end();
323 template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
325 typedef QConstByteArrayDataPtr<N> type;
326 typedef QByteArray ConvertTo;
327 enum { ExactSize = false };
328 static int size(const type &) { return N; }
329 #ifndef QT_NO_CAST_FROM_ASCII
330 static inline QT_ASCII_CAST_WARN void appendTo(const type &a, QChar *&out)
332 QAbstractConcatenable::convertFromAscii(a.ptr->data, N, out);
335 static inline void appendTo(const type &ba, char *&out)
337 const char *a = ba.ptr->data;
343 namespace QtStringBuilder {
344 template <typename A, typename B> struct ConvertToTypeHelper
345 { typedef A ConvertTo; };
346 template <typename T> struct ConvertToTypeHelper<T, QString>
347 { typedef QString ConvertTo; };
350 template <typename A, typename B>
351 struct QConcatenable< QStringBuilder<A, B> >
353 typedef QStringBuilder<A, B> type;
354 typedef typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo ConvertTo;
355 enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize };
356 static int size(const type &p)
358 return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
360 template<typename T> static inline void appendTo(const type &p, T *&out)
362 QConcatenable<A>::appendTo(p.a, out);
363 QConcatenable<B>::appendTo(p.b, out);
367 template <typename A, typename B>
368 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
369 operator%(const A &a, const B &b)
371 return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
374 // QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
375 // QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
376 #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
377 template <typename A, typename B>
378 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
379 operator+(const A &a, const B &b)
381 return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
385 template <typename A, typename B>
386 QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
388 #ifndef QT_NO_CAST_TO_ASCII
389 if (sizeof(typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type) == sizeof(QChar)) {
390 //it is not save to optimize as in utf8 it is not possible to compute the size
391 return a += QString(b);
394 int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
396 char *it = a.data() + a.size();
397 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
398 a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
402 template <typename A, typename B>
403 QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
405 int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
407 QChar *it = a.data() + a.size();
408 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
409 a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
418 #endif // QSTRINGBUILDER_H