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>
55 struct Q_CORE_EXPORT QAbstractConcatenable
58 static void convertFromAscii(const char *a, int len, QChar *&out);
59 static inline void convertFromAscii(char a, QChar *&out)
61 *out++ = QLatin1Char(a);
65 template <typename T> struct QConcatenable {};
67 template <typename A, typename B>
71 QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
73 friend class QByteArray;
75 template <typename T> T convertTo() const
77 const uint len = QConcatenable< QStringBuilder<A, B> >::size(*this);
78 T s(len, Qt::Uninitialized);
80 typename T::iterator d = s.data();
81 typename T::const_iterator const start = d;
82 QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
84 if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(len) != d - start) {
85 // this resize is necessary since we allocate a bit too much
86 // when dealing with variable sized 8-bit encodings
92 typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
93 typedef typename Concatenable::ConvertTo ConvertTo;
95 operator ConvertTo() const { return convertTo<ConvertTo>(); }
97 QByteArray toLatin1() const { return convertTo<QString>().toLatin1(); }
98 int size() const { return Concatenable::size(*this); }
105 class QStringBuilder <QString, QString>
108 QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
110 operator QString() const
111 { QString r(a); r += b; return r; }
112 QByteArray toLatin1() const { return QString(*this).toLatin1(); }
119 class QStringBuilder <QByteArray, QByteArray>
122 QStringBuilder(const QByteArray &a_, const QByteArray &b_) : a(a_), b(b_) {}
124 operator QByteArray() const
125 { QByteArray r(a); r += b; return r; }
132 template <> struct QConcatenable<char> : private QAbstractConcatenable
135 typedef QByteArray ConvertTo;
136 enum { ExactSize = true };
137 static int size(const char) { return 1; }
138 #ifndef QT_NO_CAST_FROM_ASCII
139 static inline QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
141 QAbstractConcatenable::convertFromAscii(c, out);
144 static inline void appendTo(const char c, char *&out)
148 template <> struct QConcatenable<QLatin1Char>
150 typedef QLatin1Char type;
151 typedef QString ConvertTo;
152 enum { ExactSize = true };
153 static int size(const QLatin1Char) { return 1; }
154 static inline void appendTo(const QLatin1Char c, QChar *&out)
156 static inline void appendTo(const QLatin1Char c, char *&out)
157 { *out++ = c.toLatin1(); }
160 template <> struct QConcatenable<QChar> : private QAbstractConcatenable
163 typedef QString ConvertTo;
164 enum { ExactSize = true };
165 static int size(const QChar) { return 1; }
166 static inline void appendTo(const QChar c, QChar *&out)
170 template <> struct QConcatenable<QChar::SpecialCharacter> : private QAbstractConcatenable
172 typedef QChar::SpecialCharacter type;
173 typedef QString ConvertTo;
174 enum { ExactSize = true };
175 static int size(const QChar::SpecialCharacter) { return 1; }
176 static inline void appendTo(const QChar::SpecialCharacter c, QChar *&out)
180 template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
182 typedef QCharRef type;
183 typedef QString ConvertTo;
184 enum { ExactSize = true };
185 static int size(const QCharRef &) { return 1; }
186 static inline void appendTo(const QCharRef &c, QChar *&out)
187 { *out++ = QChar(c); }
190 template <> struct QConcatenable<QLatin1String>
192 typedef QLatin1String type;
193 typedef QString ConvertTo;
194 enum { ExactSize = true };
195 static int size(const QLatin1String &a) { return a.size(); }
196 static inline void appendTo(const QLatin1String &a, QChar *&out)
198 for (const char *s = a.data(); *s; )
199 *out++ = QLatin1Char(*s++);
201 static inline void appendTo(const QLatin1String &a, char *&out)
203 for (const char *s = a.data(); *s; )
208 template <> struct QConcatenable<QString> : private QAbstractConcatenable
210 typedef QString type;
211 typedef QString ConvertTo;
212 enum { ExactSize = true };
213 static int size(const QString &a) { return a.size(); }
214 static inline void appendTo(const QString &a, QChar *&out)
216 const int n = a.size();
217 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
222 template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
224 typedef QConstStringDataPtr<N> type;
225 typedef QString ConvertTo;
226 enum { ExactSize = true };
227 static int size(const type &) { return N; }
228 static inline void appendTo(const type &a, QChar *&out)
230 memcpy(out, reinterpret_cast<const char*>(a.ptr->data), sizeof(QChar) * N);
235 template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
237 typedef QStringRef type;
238 typedef QString ConvertTo;
239 enum { ExactSize = true };
240 static int size(const QStringRef &a) { return a.size(); }
241 static inline void appendTo(const QStringRef &a, QChar *&out)
243 const int n = a.size();
244 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
249 template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
251 typedef char type[N];
252 typedef QByteArray ConvertTo;
253 enum { ExactSize = false };
254 static int size(const char[N]) { return N - 1; }
255 #ifndef QT_NO_CAST_FROM_ASCII
256 static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
258 QAbstractConcatenable::convertFromAscii(a, N - 1, out);
261 static inline void appendTo(const char a[N], char *&out)
268 template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
270 typedef const char type[N];
271 typedef QByteArray ConvertTo;
272 enum { ExactSize = false };
273 static int size(const char[N]) { return N - 1; }
274 #ifndef QT_NO_CAST_FROM_ASCII
275 static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
277 QAbstractConcatenable::convertFromAscii(a, N - 1, out);
280 static inline void appendTo(const char a[N], char *&out)
287 template <> struct QConcatenable<const char *> : private QAbstractConcatenable
289 typedef char const *type;
290 typedef QByteArray ConvertTo;
291 enum { ExactSize = false };
292 static int size(const char *a) { return qstrlen(a); }
293 #ifndef QT_NO_CAST_FROM_ASCII
294 static inline void QT_ASCII_CAST_WARN appendTo(const char *a, QChar *&out)
295 { QAbstractConcatenable::convertFromAscii(a, -1, out); }
297 static inline void appendTo(const char *a, char *&out)
306 template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
308 typedef QByteArray type;
309 typedef QByteArray ConvertTo;
310 enum { ExactSize = false };
311 static int size(const QByteArray &ba) { return ba.size(); }
312 #ifndef QT_NO_CAST_FROM_ASCII
313 static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
315 QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
318 static inline void appendTo(const QByteArray &ba, char *&out)
320 const char *a = ba.constData();
321 const char * const end = ba.end();
327 template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
329 typedef QConstByteArrayDataPtr<N> type;
330 typedef QByteArray ConvertTo;
331 enum { ExactSize = false };
332 static int size(const type &) { return N; }
333 #ifndef QT_NO_CAST_FROM_ASCII
334 static inline QT_ASCII_CAST_WARN void appendTo(const type &a, QChar *&out)
336 QAbstractConcatenable::convertFromAscii(a.ptr->data, N, out);
339 static inline void appendTo(const type &ba, char *&out)
341 const char *a = ba.ptr->data;
347 namespace QtStringBuilder {
348 template <typename A, typename B> struct ConvertToTypeHelper
349 { typedef A ConvertTo; };
350 template <typename T> struct ConvertToTypeHelper<T, QString>
351 { typedef QString ConvertTo; };
354 template <typename A, typename B>
355 struct QConcatenable< QStringBuilder<A, B> >
357 typedef QStringBuilder<A, B> type;
358 typedef typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo ConvertTo;
359 enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize };
360 static int size(const type &p)
362 return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
364 template<typename T> static inline void appendTo(const type &p, T *&out)
366 QConcatenable<A>::appendTo(p.a, out);
367 QConcatenable<B>::appendTo(p.b, out);
371 template <typename A, typename B>
372 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
373 operator%(const A &a, const B &b)
375 return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
378 // QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
379 // QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
380 #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
381 template <typename A, typename B>
382 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
383 operator+(const A &a, const B &b)
385 return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
389 template <typename A, typename B>
390 QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
392 #ifndef QT_NO_CAST_TO_ASCII
393 if (sizeof(typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type) == sizeof(QChar)) {
394 //it is not save to optimize as in utf8 it is not possible to compute the size
395 return a += QString(b);
398 int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
400 char *it = a.data() + a.size();
401 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
402 a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
406 template <typename A, typename B>
407 QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
409 int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
411 QChar *it = a.data() + a.size();
412 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
413 a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
422 #endif // QSTRINGBUILDER_H