Remove custom text codec for C strings.
[profile/ivi/qtbase.git] / src / corelib / tools / qstringbuilder.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
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         *out++ = QLatin1Char(a);
69     }
70
71     static inline void convertToAscii(QChar a, char *&out)
72     {
73         convertToLatin1(a, out);
74     }
75
76     static inline void convertToLatin1(QChar a, char *&out)
77     {
78         *out++ = a.unicode() > 0xff ? '?' : char(a.unicode());
79     }
80 };
81
82 template <typename T> struct QConcatenable {};
83
84 template <typename A, typename B>
85 class QStringBuilder
86 {
87 public:
88     QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
89 private:
90     friend class QByteArray;
91     friend class QString;
92     template <typename T> T convertTo() const
93     {
94         const uint len = QConcatenable< QStringBuilder<A, B> >::size(*this);
95         T s(len, Qt::Uninitialized);
96
97         typename T::iterator d = s.data();
98         typename T::const_iterator const start = d;
99         QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
100
101         if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && int(len) != d - start) {
102             // this resize is necessary since we allocate a bit too much
103             // when dealing with variable sized 8-bit encodings
104             s.resize(d - start);
105         }
106         return s;
107     }
108
109     typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
110     typedef typename Concatenable::ConvertTo ConvertTo;
111 public:
112     operator ConvertTo() const { return convertTo<ConvertTo>(); }
113
114     QByteArray toLatin1() const { return convertTo<QString>().toLatin1(); }
115     int size() const { return Concatenable::size(*this); }
116
117     const A &a;
118     const B &b;
119 };
120
121 template <>
122 class QStringBuilder <QString, QString>
123 {
124     public:
125         QStringBuilder(const QString &a_, const QString &b_) : a(a_), b(b_) {}
126
127         operator QString() const
128         { QString r(a); r += b; return r; }
129         QByteArray toLatin1() const { return QString(*this).toLatin1(); }
130
131         const QString &a;
132         const QString &b;
133 };
134
135 template <>
136 class QStringBuilder <QByteArray, QByteArray>
137 {
138     public:
139         QStringBuilder(const QByteArray &a_, const QByteArray &b_) : a(a_), b(b_) {}
140
141         operator QByteArray() const
142         { QByteArray r(a); r += b; return r; }
143
144         const QByteArray &a;
145         const QByteArray &b;
146 };
147
148
149 template <> struct QConcatenable<char> : private QAbstractConcatenable
150 {
151     typedef char type;
152     typedef QByteArray ConvertTo;
153     enum { ExactSize = true };
154     static int size(const char) { return 1; }
155 #ifndef QT_NO_CAST_FROM_ASCII
156     static inline QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
157     {
158         QAbstractConcatenable::convertFromAscii(c, out);
159     }
160 #endif
161     static inline void appendTo(const char c, char *&out)
162     { *out++ = c; }
163 };
164
165 template <> struct QConcatenable<QLatin1Char>
166 {
167     typedef QLatin1Char type;
168     typedef QString ConvertTo;
169     enum { ExactSize = true };
170     static int size(const QLatin1Char) { return 1; }
171     static inline void appendTo(const QLatin1Char c, QChar *&out)
172     { *out++ = c; }
173     static inline void appendTo(const QLatin1Char c, char *&out)
174     { *out++ = c.toLatin1(); }
175 };
176
177 template <> struct QConcatenable<QChar> : private QAbstractConcatenable
178 {
179     typedef QChar type;
180     typedef QString ConvertTo;
181     enum { ExactSize = true };
182     static int size(const QChar) { return 1; }
183     static inline void appendTo(const QChar c, QChar *&out)
184     { *out++ = c; }
185 #ifndef QT_NO_CAST_TO_ASCII
186     static inline QT_ASCII_CAST_WARN void appendTo(const QChar c, char *&out)
187     { convertToAscii(c, out); }
188 #endif
189 };
190
191 template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
192 {
193     typedef QCharRef type;
194     typedef QString ConvertTo;
195     enum { ExactSize = true };
196     static int size(const QCharRef &) { return 1; }
197     static inline void appendTo(const QCharRef &c, QChar *&out)
198     { *out++ = QChar(c); }
199 #ifndef QT_NO_CAST_TO_ASCII
200     static inline QT_ASCII_CAST_WARN void appendTo(const QCharRef &c, char *&out)
201     { convertToAscii(c, out); }
202 #endif
203 };
204
205 template <> struct QConcatenable<QLatin1String>
206 {
207     typedef QLatin1String type;
208     typedef QString ConvertTo;
209     enum { ExactSize = true };
210     static int size(const QLatin1String &a) { return a.size(); }
211     static inline void appendTo(const QLatin1String &a, QChar *&out)
212     {
213         for (const char *s = a.data(); *s; )
214             *out++ = QLatin1Char(*s++);
215     }
216     static inline void appendTo(const QLatin1String &a, char *&out)
217     {
218         for (const char *s = a.data(); *s; )
219             *out++ = *s++;
220     }
221 };
222
223 template <> struct QConcatenable<QString> : private QAbstractConcatenable
224 {
225     typedef QString type;
226     typedef QString ConvertTo;
227     enum { ExactSize = true };
228     static int size(const QString &a) { return a.size(); }
229     static inline void appendTo(const QString &a, QChar *&out)
230     {
231         const int n = a.size();
232         memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
233         out += n;
234     }
235 #ifndef QT_NO_CAST_TO_ASCII
236     static inline QT_ASCII_CAST_WARN void appendTo(const QString &a, char *&out)
237     { convertToAscii(a.constData(), a.length(), out); }
238 #endif
239 };
240
241 template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
242 {
243     typedef QConstStringDataPtr<N> type;
244     typedef QString ConvertTo;
245     enum { ExactSize = true };
246     static int size(const type &) { return N; }
247     static inline void appendTo(const type &a, QChar *&out)
248     {
249         memcpy(out, reinterpret_cast<const char*>(a.ptr->data), sizeof(QChar) * N);
250         out += N;
251     }
252 #ifndef QT_NO_CAST_TO_ASCII
253     static inline QT_ASCII_CAST_WARN void appendTo(const type &a, char *&out)
254     { convertToAscii(a.ptr->data, N, out); }
255 #endif
256 };
257
258 template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable
259 {
260     typedef QStringRef type;
261     typedef QString ConvertTo;
262     enum { ExactSize = true };
263     static int size(const QStringRef &a) { return a.size(); }
264     static inline void appendTo(const QStringRef &a, QChar *&out)
265     {
266         const int n = a.size();
267         memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
268         out += n;
269     }
270 #ifndef QT_NO_CAST_TO_ASCII
271     static inline QT_ASCII_CAST_WARN void appendTo(const QStringRef &a, char *&out)
272     { convertToAscii(a.constData(), a.length(), out); }
273 #endif
274
275 };
276
277 template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
278 {
279     typedef char type[N];
280     typedef QByteArray ConvertTo;
281     enum { ExactSize = false };
282     static int size(const char[N]) { return N - 1; }
283 #ifndef QT_NO_CAST_FROM_ASCII
284     static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
285     {
286         QAbstractConcatenable::convertFromAscii(a, N - 1, out);
287     }
288 #endif
289     static inline void appendTo(const char a[N], char *&out)
290     {
291         while (*a)
292             *out++ = *a++;
293     }
294 };
295
296 template <int N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
297 {
298     typedef const char type[N];
299     typedef QByteArray ConvertTo;
300     enum { ExactSize = false };
301     static int size(const char[N]) { return N - 1; }
302 #ifndef QT_NO_CAST_FROM_ASCII
303     static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
304     {
305         QAbstractConcatenable::convertFromAscii(a, N - 1, out);
306     }
307 #endif
308     static inline void appendTo(const char a[N], char *&out)
309     {
310         while (*a)
311             *out++ = *a++;
312     }
313 };
314
315 template <> struct QConcatenable<const char *> : private QAbstractConcatenable
316 {
317     typedef char const *type;
318     typedef QByteArray ConvertTo;
319     enum { ExactSize = false };
320     static int size(const char *a) { return qstrlen(a); }
321 #ifndef QT_NO_CAST_FROM_ASCII
322     static inline void QT_ASCII_CAST_WARN appendTo(const char *a, QChar *&out)
323     { QAbstractConcatenable::convertFromAscii(a, -1, out); }
324 #endif
325     static inline void appendTo(const char *a, char *&out)
326     {
327         if (!a)
328             return;
329         while (*a)
330             *out++ = *a++;
331     }
332 };
333
334 template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
335 {
336     typedef QByteArray type;
337     typedef QByteArray ConvertTo;
338     enum { ExactSize = false };
339     static int size(const QByteArray &ba) { return ba.size(); }
340 #ifndef QT_NO_CAST_FROM_ASCII
341     static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
342     {
343         QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
344     }
345 #endif
346     static inline void appendTo(const QByteArray &ba, char *&out)
347     {
348         const char *a = ba.constData();
349         const char * const end = ba.end();
350         while (a != end)
351             *out++ = *a++;
352     }
353 };
354
355 template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
356 {
357     typedef QConstByteArrayDataPtr<N> type;
358     typedef QByteArray ConvertTo;
359     enum { ExactSize = false };
360     static int size(const type &) { return N; }
361 #ifndef QT_NO_CAST_FROM_ASCII
362     static inline QT_ASCII_CAST_WARN void appendTo(const type &a, QChar *&out)
363     {
364         QAbstractConcatenable::convertFromAscii(a.ptr->data, N, out);
365     }
366 #endif
367     static inline void appendTo(const type &ba, char *&out)
368     {
369         const char *a = ba.ptr->data;
370         while (*a)
371             *out++ = *a++;
372     }
373 };
374
375 namespace QtStringBuilder {
376     template <typename A, typename B> struct ConvertToTypeHelper
377     { typedef A ConvertTo; };
378     template <typename T> struct ConvertToTypeHelper<T, QString>
379     { typedef QString ConvertTo; };
380 }
381
382 template <typename A, typename B>
383 struct QConcatenable< QStringBuilder<A, B> >
384 {
385     typedef QStringBuilder<A, B> type;
386     typedef typename QtStringBuilder::ConvertToTypeHelper<typename QConcatenable<A>::ConvertTo, typename QConcatenable<B>::ConvertTo>::ConvertTo ConvertTo;
387     enum { ExactSize = QConcatenable<A>::ExactSize && QConcatenable<B>::ExactSize };
388     static int size(const type &p)
389     {
390         return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
391     }
392     template<typename T> static inline void appendTo(const type &p, T *&out)
393     {
394         QConcatenable<A>::appendTo(p.a, out);
395         QConcatenable<B>::appendTo(p.b, out);
396     }
397 };
398
399 template <typename A, typename B>
400 QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
401 operator%(const A &a, const B &b)
402 {
403    return QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>(a, b);
404 }
405
406 // QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
407 // QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
408 #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
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 #endif
416
417 template <typename A, typename B>
418 QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
419 {
420 #ifndef QT_NO_CAST_TO_ASCII
421     if (sizeof(typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type) == sizeof(QChar)) {
422         //it is not save to optimize as in utf8 it is not possible to compute the size
423         return a += QString(b);
424     }
425 #endif
426     int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
427     a.reserve(len);
428     char *it = a.data() + a.size();
429     QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
430     a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
431     return a;
432 }
433
434 template <typename A, typename B>
435 QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
436 {
437     int len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
438     a.reserve(len);
439     QChar *it = a.data() + a.size();
440     QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
441     a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
442     return a;
443 }
444
445
446 QT_END_NAMESPACE
447
448 QT_END_HEADER
449
450 #endif // QSTRINGBUILDER_H