Remove use of QT_MODULE from library
[profile/ivi/qtbase.git] / src / corelib / tools / qstringbuilder.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QSTRINGBUILDER_H
43 #define QSTRINGBUILDER_H
44
45 #include <QtCore/qstring.h>
46 #include <QtCore/qbytearray.h>
47
48 #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
49 #  if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
50 #    include <QtCore/qmap.h>
51 #  endif
52 #endif
53
54 #include <string.h>
55
56 QT_BEGIN_HEADER
57
58 QT_BEGIN_NAMESPACE
59
60
61 struct Q_CORE_EXPORT QAbstractConcatenable
62 {
63 protected:
64     static void convertFromAscii(const char *a, int len, QChar *&out);
65     static void convertToAscii(const QChar *a, int len, char *&out);
66     static inline void convertFromAscii(char a, QChar *&out)
67     {
68 #ifndef QT_NO_TEXTCODEC
69         if (QString::codecForCStrings)
70             *out++ = QChar::fromAscii(a);
71         else
72 #endif
73             *out++ = QLatin1Char(a);
74     }
75
76     static inline void convertToAscii(QChar a, char *&out)
77     {
78 #ifndef QT_NO_TEXTCODEC
79         if (QString::codecForCStrings)
80             *out++ = a.toAscii(); //###
81         else
82 #endif
83             convertToLatin1(a, out);
84     }
85
86     static inline void convertToLatin1(QChar a, char *&out)
87     {
88         *out++ = a.unicode() > 0xff ? '?' : char(a.unicode());
89     }
90 };
91
92 template <typename T> struct QConcatenable {};
93
94 template <typename A, typename B>
95 class QStringBuilder
96 {
97 public:
98     QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
99 private:
100     friend class QByteArray;
101     friend class QString;
102     template <typename T> T convertTo() const
103     {
104         const uint len = QConcatenable< QStringBuilder<A, B> >::size(*this);
105         T s(len, Qt::Uninitialized);
106
107         typename T::iterator d = s.data();
108         typename T::const_iterator const start = d;
109         QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
110
111         if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(len) != d - start) {
112             // this resize is necessary since we allocate a bit too much
113             // when dealing with variable sized 8-bit encodings
114             s.resize(d - start);
115         }
116         return s;
117     }
118
119     typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
120     typedef typename Concatenable::ConvertTo ConvertTo;
121 public:
122     operator ConvertTo() const { return convertTo<ConvertTo>(); }
123
124     QByteArray toLatin1() const { return convertTo<QString>().toLatin1(); }
125     int size() const { return Concatenable::size(*this); }
126
127     const A &a;
128     const B &b;
129 };
130
131 template <>
132 class QStringBuilder <QString, QString>
133 {
134     public:
135         QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
136
137         operator QString() const
138         { QString r(a); r += b; return r; }
139         QByteArray toLatin1() const { return QString(*this).toLatin1(); }
140
141         const QString &a;
142         const QString &b;
143 };
144
145 template <>
146 class QStringBuilder <QByteArray, QByteArray>
147 {
148     public:
149         QStringBuilder(const QByteArray &a_, const QByteArray &b_) : a(a_), b(b_) {}
150
151         operator QByteArray() const
152         { QByteArray r(a); r += b; return r; }
153
154         const QByteArray &a;
155         const QByteArray &b;
156 };
157
158
159 template <> struct QConcatenable<char> : private QAbstractConcatenable
160 {
161     typedef char type;
162     typedef QByteArray ConvertTo;
163     enum { ExactSize = true };
164     static int size(const char) { return 1; }
165 #ifndef QT_NO_CAST_FROM_ASCII
166     static inline QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
167     {
168         QAbstractConcatenable::convertFromAscii(c, out);
169     }
170 #endif
171     static inline void appendTo(const char c, char *&out)
172     { *out++ = c; }
173 };
174
175 template <> struct QConcatenable<QLatin1Char>
176 {
177     typedef QLatin1Char type;
178     typedef QString ConvertTo;
179     enum { ExactSize = true };
180     static int size(const QLatin1Char) { return 1; }
181     static inline void appendTo(const QLatin1Char c, QChar *&out)
182     { *out++ = c; }
183     static inline void appendTo(const QLatin1Char c, char *&out)
184     { *out++ = c.toLatin1(); }
185 };
186
187 template <> struct QConcatenable<QChar> : private QAbstractConcatenable
188 {
189     typedef QChar type;
190     typedef QString ConvertTo;
191     enum { ExactSize = true };
192     static int size(const QChar) { return 1; }
193     static inline void appendTo(const QChar c, QChar *&out)
194     { *out++ = c; }
195 #ifndef QT_NO_CAST_TO_ASCII
196     static inline QT_ASCII_CAST_WARN void appendTo(const QChar c, char *&out)
197     { convertToAscii(c, out); }
198 #endif
199 };
200
201 template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
202 {
203     typedef QCharRef type;
204     typedef QString ConvertTo;
205     enum { ExactSize = true };
206     static int size(const QCharRef &) { return 1; }
207     static inline void appendTo(const QCharRef &c, QChar *&out)
208     { *out++ = QChar(c); }
209 #ifndef QT_NO_CAST_TO_ASCII
210     static inline QT_ASCII_CAST_WARN void appendTo(const QCharRef &c, char *&out)
211     { convertToAscii(c, out); }
212 #endif
213 };
214
215 template <> struct QConcatenable<QLatin1String>
216 {
217     typedef QLatin1String type;
218     typedef QString ConvertTo;
219     enum { ExactSize = true };
220     static int size(const QLatin1String &a) { return a.size(); }
221     static inline void appendTo(const QLatin1String &a, QChar *&out)
222     {
223         for (const char *s = a.data(); *s; )
224             *out++ = QLatin1Char(*s++);
225     }
226     static inline void appendTo(const QLatin1String &a, char *&out)
227     {
228         for (const char *s = a.data(); *s; )
229             *out++ = *s++;
230     }
231 };
232
233 template <> struct QConcatenable<QString> : private QAbstractConcatenable
234 {
235     typedef QString type;
236     typedef QString ConvertTo;
237     enum { ExactSize = true };
238     static int size(const QString &a) { return a.size(); }
239     static inline void appendTo(const QString &a, QChar *&out)
240     {
241         const int n = a.size();
242         memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
243         out += n;
244     }
245 #ifndef QT_NO_CAST_TO_ASCII
246     static inline QT_ASCII_CAST_WARN void appendTo(const QString &a, char *&out)
247     { convertToAscii(a.constData(), a.length(), out); }
248 #endif
249 };
250
251 template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
252 {
253     typedef QConstStringDataPtr<N> type;
254     typedef QString ConvertTo;
255     enum { ExactSize = true };
256     static int size(const type &) { return N; }
257     static inline void appendTo(const type &a, QChar *&out)
258     {
259         memcpy(out, reinterpret_cast<const char*>(a.ptr->data), sizeof(QChar) * N);
260         out += N;
261     }
262 #ifndef QT_NO_CAST_TO_ASCII
263     static inline QT_ASCII_CAST_WARN void appendTo(const type &a, char *&out)
264     { convertToAscii(a.ptr->data, N, out); }
265 #endif
266 };
267
268 template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
269 {
270     typedef QStringRef type;
271     typedef QString ConvertTo;
272     enum { ExactSize = true };
273     static int size(const QStringRef &a) { return a.size(); }
274     static inline void appendTo(const QStringRef &a, QChar *&out)
275     {
276         const int n = a.size();
277         memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
278         out += n;
279     }
280 #ifndef QT_NO_CAST_TO_ASCII
281     static inline QT_ASCII_CAST_WARN void appendTo(const QStringRef &a, char *&out)
282     { convertToAscii(a.constData(), a.length(), out); }
283 #endif
284
285 };
286
287 template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
288 {
289     typedef char type[N];
290     typedef QByteArray ConvertTo;
291     enum { ExactSize = false };
292     static int size(const char[N]) { return N - 1; }
293 #ifndef QT_NO_CAST_FROM_ASCII
294     static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
295     {
296         QAbstractConcatenable::convertFromAscii(a, N - 1, out);
297     }
298 #endif
299     static inline void appendTo(const char a[N], char *&out)
300     {
301         while (*a)
302             *out++ = *a++;
303     }
304 };
305
306 template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
307 {
308     typedef const char type[N];
309     typedef QByteArray ConvertTo;
310     enum { ExactSize = false };
311     static int size(const char[N]) { return N - 1; }
312 #ifndef QT_NO_CAST_FROM_ASCII
313     static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
314     {
315         QAbstractConcatenable::convertFromAscii(a, N - 1, out);
316     }
317 #endif
318     static inline void appendTo(const char a[N], char *&out)
319     {
320         while (*a)
321             *out++ = *a++;
322     }
323 };
324
325 template <> struct QConcatenable<const char *> : private QAbstractConcatenable
326 {
327     typedef char const *type;
328     typedef QByteArray ConvertTo;
329     enum { ExactSize = false };
330     static int size(const char *a) { return qstrlen(a); }
331 #ifndef QT_NO_CAST_FROM_ASCII
332     static inline void QT_ASCII_CAST_WARN appendTo(const char *a, QChar *&out)
333     { QAbstractConcatenable::convertFromAscii(a, -1, out); }
334 #endif
335     static inline void appendTo(const char *a, char *&out)
336     {
337         if (!a)
338             return;
339         while (*a)
340             *out++ = *a++;
341     }
342 };
343
344 template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
345 {
346     typedef QByteArray type;
347     typedef QByteArray ConvertTo;
348     enum { ExactSize = false };
349     static int size(const QByteArray &ba) { return ba.size(); }
350 #ifndef QT_NO_CAST_FROM_ASCII
351     static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
352     {
353         QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
354     }
355 #endif
356     static inline void appendTo(const QByteArray &ba, char *&out)
357     {
358         const char *a = ba.constData();
359         const char * const end = ba.end();
360         while (a != end)
361             *out++ = *a++;
362     }
363 };
364
365 template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
366 {
367     typedef QConstByteArrayDataPtr<N> type;
368     typedef QByteArray ConvertTo;
369     enum { ExactSize = false };
370     static int size(const type &) { return N; }
371 #ifndef QT_NO_CAST_FROM_ASCII
372     static inline QT_ASCII_CAST_WARN void appendTo(const type &a, QChar *&out)
373     {
374         QAbstractConcatenable::convertFromAscii(a.ptr->data, N, out);
375     }
376 #endif
377     static inline void appendTo(const type &ba, char *&out)
378     {
379         const char *a = ba.ptr->data;
380         while (*a)
381             *out++ = *a++;
382     }
383 };
384
385 namespace QtStringBuilder {
386     template <typename A, typename B> struct ConvertToTypeHelper
387     { typedef A ConvertTo; };
388     template <typename T> struct ConvertToTypeHelper<T, QString>
389     { typedef QString ConvertTo; };
390 }
391
392 template <typename A, typename B>
393 struct QConcatenable< QStringBuilder<A, B> >
394 {
395     typedef QStringBuilder<A, B> type;
396     typedef typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo ConvertTo;
397     enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize };
398     static int size(const type &p)
399     {
400         return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
401     }
402     template<typename T> static inline void appendTo(const type &p, T *&out)
403     {
404         QConcatenable<A>::appendTo(p.a, out);
405         QConcatenable<B>::appendTo(p.b, out);
406     }
407 };
408
409 template <typename A, typename B>
410 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
411 operator%(const A &a, const B &b)
412 {
413    return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
414 }
415
416 // QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
417 // QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
418 #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
419 template <typename A, typename B>
420 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
421 operator+(const A &a, const B &b)
422 {
423    return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
424 }
425 #endif
426
427 template <typename A, typename B>
428 QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
429 {
430 #ifndef QT_NO_CAST_TO_ASCII
431     if (sizeof(typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type) == sizeof(QChar)) {
432         //it is not save to optimize as in utf8 it is not possible to compute the size
433         return a += QString(b);
434     }
435 #endif
436     int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
437     a.reserve(len);
438     char *it = a.data() + a.size();
439     QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
440     a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
441     return a;
442 }
443
444 template <typename A, typename B>
445 QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
446 {
447     int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
448     a.reserve(len);
449     QChar *it = a.data() + a.size();
450     QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
451     a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
452     return a;
453 }
454
455
456 QT_END_NAMESPACE
457
458 QT_END_HEADER
459
460 #endif // QSTRINGBUILDER_H