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
46 // syncqt can not handle the templates in this file, and it doesn't need to
47 // process them anyway because they are internal.
48 #pragma qt_class(QStringBuilder)
49 #pragma qt_sync_stop_processing
52 #include <QtCore/qstring.h>
53 #include <QtCore/qbytearray.h>
62 struct Q_CORE_EXPORT QAbstractConcatenable
65 static void convertFromAscii(const char *a, int len, QChar *&out);
66 static inline void convertFromAscii(char a, QChar *&out)
68 *out++ = QLatin1Char(a);
72 template <typename T> struct QConcatenable {};
74 namespace QtStringBuilder {
75 template <typename A, typename B> struct ConvertToTypeHelper
76 { typedef A ConvertTo; };
77 template <typename T> struct ConvertToTypeHelper<T, QString>
78 { typedef QString ConvertTo; };
81 template<typename Builder, typename T>
82 struct QStringBuilderCommon
84 T toUpper() const { return resolved().toUpper(); }
85 T toLower() const { return resolved().toLower(); }
88 const T resolved() const { return *static_cast<const Builder*>(this); }
91 template<typename Builder, typename T>
92 struct QStringBuilderBase : public QStringBuilderCommon<Builder, T>
96 template<typename Builder>
97 struct QStringBuilderBase<Builder, QString> : public QStringBuilderCommon<Builder, QString>
99 QByteArray toLatin1() const { return this->resolved().toLatin1(); }
100 QByteArray toLocal8Bit() const { return this->resolved().toLocal8Bit(); }
103 template <typename A, typename B>
104 class QStringBuilder : public QStringBuilderBase<QStringBuilder<A, B>, typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo>
107 QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
109 friend class QByteArray;
110 friend class QString;
111 template <typename T> T convertTo() const
113 const uint len = QConcatenable< QStringBuilder<A, B> >::size(*this);
114 T s(len, Qt::Uninitialized);
116 typename T::iterator d = s.data();
117 typename T::const_iterator const start = d;
118 QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
120 if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(len) != d - start) {
121 // this resize is necessary since we allocate a bit too much
122 // when dealing with variable sized 8-bit encodings
128 typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
129 typedef typename Concatenable::ConvertTo ConvertTo;
131 operator ConvertTo() const { return convertTo<ConvertTo>(); }
133 int size() const { return Concatenable::size(*this); }
140 class QStringBuilder <QString, QString> : public QStringBuilderBase<QStringBuilder<QString, QString>, QString>
143 QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
145 operator QString() const
146 { QString r(a); r += b; return r; }
153 class QStringBuilder <QByteArray, QByteArray> : public QStringBuilderBase<QStringBuilder<QByteArray, QByteArray>, QByteArray>
156 QStringBuilder(const QByteArray &a_, const QByteArray &b_) : a(a_), b(b_) {}
158 operator QByteArray() const
159 { QByteArray r(a); r += b; return r; }
166 template <> struct QConcatenable<char> : private QAbstractConcatenable
169 typedef QByteArray ConvertTo;
170 enum { ExactSize = true };
171 static int size(const char) { return 1; }
172 #ifndef QT_NO_CAST_FROM_ASCII
173 static inline QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
175 QAbstractConcatenable::convertFromAscii(c, out);
178 static inline void appendTo(const char c, char *&out)
182 template <> struct QConcatenable<QLatin1Char>
184 typedef QLatin1Char type;
185 typedef QString ConvertTo;
186 enum { ExactSize = true };
187 static int size(const QLatin1Char) { return 1; }
188 static inline void appendTo(const QLatin1Char c, QChar *&out)
190 static inline void appendTo(const QLatin1Char c, char *&out)
191 { *out++ = c.toLatin1(); }
194 template <> struct QConcatenable<QChar> : private QAbstractConcatenable
197 typedef QString ConvertTo;
198 enum { ExactSize = true };
199 static int size(const QChar) { return 1; }
200 static inline void appendTo(const QChar c, QChar *&out)
204 template <> struct QConcatenable<QChar::SpecialCharacter> : private QAbstractConcatenable
206 typedef QChar::SpecialCharacter type;
207 typedef QString ConvertTo;
208 enum { ExactSize = true };
209 static int size(const QChar::SpecialCharacter) { return 1; }
210 static inline void appendTo(const QChar::SpecialCharacter c, QChar *&out)
214 template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
216 typedef QCharRef type;
217 typedef QString ConvertTo;
218 enum { ExactSize = true };
219 static int size(const QCharRef &) { return 1; }
220 static inline void appendTo(const QCharRef &c, QChar *&out)
221 { *out++ = QChar(c); }
224 template <> struct QConcatenable<QLatin1String>
226 typedef QLatin1String type;
227 typedef QString ConvertTo;
228 enum { ExactSize = true };
229 static int size(const QLatin1String &a) { return a.size(); }
230 static inline void appendTo(const QLatin1String &a, QChar *&out)
232 for (const char *s = a.data(); *s; )
233 *out++ = QLatin1Char(*s++);
235 static inline void appendTo(const QLatin1String &a, char *&out)
237 for (const char *s = a.data(); *s; )
242 template <> struct QConcatenable<QString> : private QAbstractConcatenable
244 typedef QString type;
245 typedef QString ConvertTo;
246 enum { ExactSize = true };
247 static int size(const QString &a) { return a.size(); }
248 static inline void appendTo(const QString &a, QChar *&out)
250 const int n = a.size();
251 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
256 template <> struct QConcatenable<QStringDataPtr> : private QAbstractConcatenable
258 typedef QStringDataPtr type;
259 typedef QString ConvertTo;
260 enum { ExactSize = true };
261 static int size(const type &a) { return a.ptr->size; }
262 static inline void appendTo(const type &a, QChar *&out)
264 memcpy(out, reinterpret_cast<const char*>(a.ptr->data()), sizeof(QChar) * a.ptr->size);
269 template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
271 typedef QStringRef type;
272 typedef QString ConvertTo;
273 enum { ExactSize = true };
274 static int size(const QStringRef &a) { return a.size(); }
275 static inline void appendTo(const QStringRef &a, QChar *&out)
277 const int n = a.size();
278 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
283 template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
285 typedef char type[N];
286 typedef QByteArray ConvertTo;
287 enum { ExactSize = false };
288 static int size(const char[N]) { return N - 1; }
289 #ifndef QT_NO_CAST_FROM_ASCII
290 static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
292 QAbstractConcatenable::convertFromAscii(a, N - 1, out);
295 static inline void appendTo(const char a[N], char *&out)
302 template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
304 typedef const char type[N];
305 typedef QByteArray ConvertTo;
306 enum { ExactSize = false };
307 static int size(const char[N]) { return N - 1; }
308 #ifndef QT_NO_CAST_FROM_ASCII
309 static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
311 QAbstractConcatenable::convertFromAscii(a, N - 1, out);
314 static inline void appendTo(const char a[N], char *&out)
321 template <> struct QConcatenable<const char *> : private QAbstractConcatenable
323 typedef char const *type;
324 typedef QByteArray ConvertTo;
325 enum { ExactSize = false };
326 static int size(const char *a) { return qstrlen(a); }
327 #ifndef QT_NO_CAST_FROM_ASCII
328 static inline void QT_ASCII_CAST_WARN appendTo(const char *a, QChar *&out)
329 { QAbstractConcatenable::convertFromAscii(a, -1, out); }
331 static inline void appendTo(const char *a, char *&out)
340 template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
342 typedef QByteArray type;
343 typedef QByteArray ConvertTo;
344 enum { ExactSize = false };
345 static int size(const QByteArray &ba) { return ba.size(); }
346 #ifndef QT_NO_CAST_FROM_ASCII
347 static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
349 QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
352 static inline void appendTo(const QByteArray &ba, char *&out)
354 const char *a = ba.constData();
355 const char * const end = ba.end();
361 template <> struct QConcatenable<QByteArrayDataPtr> : private QAbstractConcatenable
363 typedef QByteArrayDataPtr type;
364 typedef QByteArray ConvertTo;
365 enum { ExactSize = false };
366 static int size(const type &ba) { return ba.ptr->size; }
367 #ifndef QT_NO_CAST_FROM_ASCII
368 static inline QT_ASCII_CAST_WARN void appendTo(const type &a, QChar *&out)
370 QAbstractConcatenable::convertFromAscii(a.ptr->data(), a.ptr->size, out);
373 static inline void appendTo(const type &ba, char *&out)
375 ::memcpy(out, ba.ptr->data(), ba.ptr->size);
380 template <typename A, typename B>
381 struct QConcatenable< QStringBuilder<A, B> >
383 typedef QStringBuilder<A, B> type;
384 typedef typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo ConvertTo;
385 enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize };
386 static int size(const type &p)
388 return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
390 template<typename T> static inline void appendTo(const type &p, T *&out)
392 QConcatenable<A>::appendTo(p.a, out);
393 QConcatenable<B>::appendTo(p.b, out);
397 template <typename A, typename B>
398 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
399 operator%(const A &a, const B &b)
401 return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
404 // QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
405 // QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
406 #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
407 template <typename A, typename B>
408 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
409 operator+(const A &a, const B &b)
411 return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
415 template <typename A, typename B>
416 QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
418 #ifndef QT_NO_CAST_TO_ASCII
419 if (sizeof(typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type) == sizeof(QChar)) {
420 //it is not save to optimize as in utf8 it is not possible to compute the size
421 return a += QString(b);
424 int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
426 char *it = a.data() + a.size();
427 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
428 a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
432 template <typename A, typename B>
433 QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
435 int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
437 QChar *it = a.data() + a.size();
438 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
439 a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
448 #endif // QSTRINGBUILDER_H