1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include <QtTest/QtTest> |
30 | |
31 | #define LITERAL "some literal" |
32 | #define LITERAL_LEN (sizeof(LITERAL)-1) |
33 | #define "some literal" "EXTRA" |
34 | |
35 | // "some literal", but replacing all vowels by their umlauted UTF-8 string :) |
36 | #define UTF8_LITERAL "s\xc3\xb6m\xc3\xab l\xc3\xaft\xc3\xabr\xc3\xa4l" |
37 | #define UTF8_LITERAL_LEN (sizeof(UTF8_LITERAL)-1) |
38 | #define "s\xc3\xb6m\xc3\xab l\xc3\xaft\xc3\xabr\xc3\xa4l" "EXTRA" |
39 | |
40 | #ifdef Q_COMPILER_UNICODE_STRINGS |
41 | // "some literal", but replacing all vocals by their umlauted UTF-8 string :) |
42 | #define UNICODE_LITERAL u"s\u00f6m\u00eb l\u00eft\u00ebr\u00e4l" |
43 | #define UNICODE_LITERAL_LEN ((sizeof(UNICODE_LITERAL) - 1) / 2) |
44 | #define u"s\u00f6m\u00eb l\u00eft\u00ebr\u00e4l" "EXTRA" |
45 | #endif |
46 | |
47 | #ifndef P |
48 | # error You need to define P |
49 | # define P + |
50 | #endif |
51 | |
52 | //fix for gcc4.0: if the operator+ does not exist without QT_USE_FAST_OPERATOR_PLUS |
53 | #ifndef QT_USE_FAST_CONCATENATION |
54 | #define Q % |
55 | #else |
56 | #define Q P |
57 | #endif |
58 | |
59 | template <typename T> QString toQString(const T &t); |
60 | |
61 | template <> QString toQString(const QString &s) { return s; } |
62 | template <> QString toQString(const QStringRef &r) { return r.toString(); } |
63 | template <> QString toQString(const QStringView &v) { return v.toString(); } |
64 | template <> QString toQString(const QLatin1String &l) { return l; } |
65 | template <> QString toQString(const QLatin1Char &l) { return QChar(l); } |
66 | template <> QString toQString(const QChar &c) { return c; } |
67 | template <> QString toQString(const QChar::SpecialCharacter &c) { return QChar(c); } |
68 | #ifdef Q_COMPILER_UNICODE_STRINGS |
69 | template <> QString toQString(char16_t * const &p) { return QStringView(p).toString(); } |
70 | template <size_t N> QString toQString(const char16_t (&a)[N]) { return QStringView(a).toString(); } |
71 | template <> QString toQString(const char16_t &c) { return QChar(c); } |
72 | #endif |
73 | |
74 | template <typename T> QByteArray toQByteArray(const T &t); |
75 | |
76 | template <> QByteArray toQByteArray(const QByteArray &b) { return b; } |
77 | template <> QByteArray toQByteArray(char * const &p) { return p; } |
78 | template <size_t N> QByteArray toQByteArray(const char (&a)[N]) { return a; } |
79 | template <> QByteArray toQByteArray(const char &c) { return QByteArray(&c, 1); } |
80 | |
81 | void runScenario() |
82 | { |
83 | // this code is latin1. TODO: replace it with the utf8 block below, once |
84 | // strings default to utf8. |
85 | QLatin1String l1string(LITERAL); |
86 | QString string(l1string); |
87 | QStringRef stringref(&string, 2, 10); |
88 | QStringView stringview(stringref); |
89 | QLatin1Char lchar('c'); |
90 | QChar qchar(lchar); |
91 | QChar::SpecialCharacter special(QChar::Nbsp); |
92 | #ifdef Q_COMPILER_UNICODE_STRINGS |
93 | char16_t u16char = UNICODE_LITERAL[0]; |
94 | char16_t u16chararray[] = { u's', 0xF6, u'm', 0xEB, u' ', u'l', 0xEF, u't', 0xEB, u'r', 0xE4, u'l', 0x00 }; |
95 | QCOMPARE(QStringView(u16chararray), QStringView(UNICODE_LITERAL)); |
96 | char16_t *u16charstar = u16chararray; |
97 | #endif |
98 | |
99 | #define CHECK(QorP, a1, a2) \ |
100 | do { \ |
101 | DO(QorP, a1, a2); \ |
102 | DO(QorP, a2, a1); \ |
103 | } while (0) |
104 | |
105 | #define DO(QorP, a1, a2) \ |
106 | QCOMPARE(QString(a1 QorP a2), \ |
107 | toQString(a1).append(toQString(a2))) \ |
108 | /* end */ |
109 | |
110 | CHECK(P, l1string, l1string); |
111 | CHECK(P, l1string, string); |
112 | CHECK(P, l1string, stringref); |
113 | CHECK(Q, l1string, stringview); |
114 | CHECK(P, l1string, lchar); |
115 | CHECK(P, l1string, qchar); |
116 | CHECK(P, l1string, special); |
117 | CHECK(P, l1string, QStringLiteral(LITERAL)); |
118 | CHECK(Q, l1string, u16char); |
119 | CHECK(Q, l1string, u16chararray); |
120 | CHECK(Q, l1string, u16charstar); |
121 | |
122 | CHECK(P, string, string); |
123 | CHECK(P, string, stringref); |
124 | CHECK(Q, string, stringview); |
125 | CHECK(P, string, lchar); |
126 | CHECK(P, string, qchar); |
127 | CHECK(P, string, special); |
128 | CHECK(P, string, QStringLiteral(LITERAL)); |
129 | CHECK(Q, string, u16char); |
130 | CHECK(Q, string, u16chararray); |
131 | CHECK(Q, string, u16charstar); |
132 | |
133 | CHECK(P, stringref, stringref); |
134 | CHECK(Q, stringref, stringview); |
135 | CHECK(P, stringref, lchar); |
136 | CHECK(P, stringref, qchar); |
137 | CHECK(P, stringref, special); |
138 | CHECK(P, stringref, QStringLiteral(LITERAL)); |
139 | CHECK(Q, stringref, u16char); |
140 | CHECK(Q, stringref, u16chararray); |
141 | CHECK(Q, stringref, u16charstar); |
142 | |
143 | CHECK(Q, stringview, stringview); |
144 | CHECK(Q, stringview, lchar); |
145 | CHECK(Q, stringview, qchar); |
146 | CHECK(Q, stringview, special); |
147 | CHECK(P, stringview, QStringLiteral(LITERAL)); |
148 | CHECK(Q, stringview, u16char); |
149 | CHECK(Q, stringview, u16chararray); |
150 | CHECK(Q, stringview, u16charstar); |
151 | |
152 | CHECK(P, lchar, lchar); |
153 | CHECK(P, lchar, qchar); |
154 | CHECK(P, lchar, special); |
155 | CHECK(P, lchar, QStringLiteral(LITERAL)); |
156 | CHECK(Q, lchar, u16char); |
157 | CHECK(Q, lchar, u16chararray); |
158 | CHECK(Q, lchar, u16charstar); |
159 | |
160 | CHECK(P, qchar, qchar); |
161 | CHECK(P, qchar, special); |
162 | CHECK(P, qchar, QStringLiteral(LITERAL)); |
163 | CHECK(Q, qchar, u16char); |
164 | CHECK(Q, qchar, u16chararray); |
165 | CHECK(Q, qchar, u16charstar); |
166 | |
167 | CHECK(P, special, special); |
168 | CHECK(P, special, QStringLiteral(LITERAL)); |
169 | CHECK(Q, special, u16char); |
170 | CHECK(Q, special, u16chararray); |
171 | CHECK(Q, special, u16charstar); |
172 | |
173 | CHECK(P, QStringLiteral(LITERAL), QStringLiteral(LITERAL)); |
174 | CHECK(Q, QStringLiteral(LITERAL), u16char); |
175 | CHECK(Q, QStringLiteral(LITERAL), u16chararray); |
176 | CHECK(Q, QStringLiteral(LITERAL), u16charstar); |
177 | |
178 | // CHECK(Q, u16char, u16char); // BUILTIN <-> BUILTIN cat't be overloaded |
179 | // CHECK(Q, u16char, u16chararray); |
180 | // CHECK(Q, u16char, u16charstar); |
181 | |
182 | // CHECK(Q, u16chararray, u16chararray); // BUILTIN <-> BUILTIN cat't be overloaded |
183 | // CHECK(Q, u16chararray, u16charstar); |
184 | |
185 | // CHECK(Q, u16charstar, u16charstar); // BUILTIN <-> BUILTIN cat't be overloaded |
186 | |
187 | #undef DO |
188 | |
189 | #define DO(QorP, a1, a2) \ |
190 | QCOMPARE(QByteArray(a1 QorP a2), \ |
191 | toQByteArray(a1).append(toQByteArray(a2))) \ |
192 | /* end */ |
193 | |
194 | QByteArray bytearray = stringref.toUtf8(); |
195 | char *charstar = bytearray.data(); |
196 | char chararray[3] = { 'H', 'i', '\0' }; |
197 | const char constchararray[3] = { 'H', 'i', '\0' }; |
198 | char achar = 'a'; |
199 | |
200 | CHECK(P, bytearray, bytearray); |
201 | CHECK(P, bytearray, charstar); |
202 | #ifndef Q_CC_MSVC // see QTBUG-65359 |
203 | CHECK(P, bytearray, chararray); |
204 | #else |
205 | Q_UNUSED(chararray); |
206 | #endif |
207 | CHECK(P, bytearray, constchararray); |
208 | CHECK(P, bytearray, achar); |
209 | |
210 | //CHECK(Q, charstar, charstar); // BUILTIN <-> BUILTIN cat't be overloaded |
211 | //CHECK(Q, charstar, chararray); |
212 | //CHECK(Q, charstar, achar); |
213 | |
214 | //CHECK(Q, chararray, chararray); // BUILTIN <-> BUILTIN cat't be overloaded |
215 | //CHECK(Q, chararray, achar); |
216 | |
217 | //CHECK(Q, achar, achar); // BUILTIN <-> BUILTIN cat't be overloaded |
218 | |
219 | #undef DO |
220 | #undef CHECK |
221 | |
222 | QString r2(QLatin1String(LITERAL LITERAL)); |
223 | QString r3 = QString::fromUtf8(UTF8_LITERAL UTF8_LITERAL); |
224 | QString r; |
225 | |
226 | // self-assignment: |
227 | r = stringref.toString(); |
228 | r = lchar + r; |
229 | QCOMPARE(r, QString(lchar P stringref)); |
230 | |
231 | #ifdef Q_COMPILER_UNICODE_STRINGS |
232 | r = QStringLiteral(UNICODE_LITERAL); |
233 | r = r Q QStringLiteral(UNICODE_LITERAL); |
234 | QCOMPARE(r, r3); |
235 | #endif |
236 | |
237 | #ifndef QT_NO_CAST_FROM_ASCII |
238 | r = string P LITERAL; |
239 | QCOMPARE(r, r2); |
240 | r = LITERAL P string; |
241 | QCOMPARE(r, r2); |
242 | |
243 | QByteArray ba = QByteArray(LITERAL); |
244 | r = ba P string; |
245 | QCOMPARE(r, r2); |
246 | r = string P ba; |
247 | QCOMPARE(r, r2); |
248 | |
249 | r = string P QByteArrayLiteral(LITERAL); |
250 | QCOMPARE(r, r2); |
251 | r = QByteArrayLiteral(LITERAL) P string; |
252 | QCOMPARE(r, r2); |
253 | |
254 | static const char badata[] = LITERAL_EXTRA; |
255 | ba = QByteArray::fromRawData(badata, LITERAL_LEN); |
256 | r = ba P string; |
257 | QCOMPARE(r, r2); |
258 | r = string P ba; |
259 | QCOMPARE(r, r2); |
260 | |
261 | string = QString::fromUtf8(UTF8_LITERAL); |
262 | ba = UTF8_LITERAL; |
263 | |
264 | r = string P UTF8_LITERAL; |
265 | QCOMPARE(r.size(), r3.size()); |
266 | QCOMPARE(r, r3); |
267 | r = UTF8_LITERAL P string; |
268 | QCOMPARE(r, r3); |
269 | r = ba P string; |
270 | QCOMPARE(r, r3); |
271 | r = string P ba; |
272 | QCOMPARE(r, r3); |
273 | |
274 | ba = QByteArray::fromRawData(UTF8_LITERAL_EXTRA, UTF8_LITERAL_LEN); |
275 | r = ba P string; |
276 | QCOMPARE(r, r3); |
277 | r = string P ba; |
278 | QCOMPARE(r, r3); |
279 | |
280 | ba = QByteArray(); // empty |
281 | r = ba P string; |
282 | QCOMPARE(r, string); |
283 | r = string P ba; |
284 | QCOMPARE(r, string); |
285 | |
286 | const char *zero = 0; |
287 | r = string P zero; |
288 | QCOMPARE(r, string); |
289 | r = zero P string; |
290 | QCOMPARE(r, string); |
291 | #endif |
292 | |
293 | string = QString::fromLatin1(LITERAL); |
294 | QCOMPARE(QByteArray(qPrintable(string P string)), QByteArray(string.toLatin1() + string.toLatin1())); |
295 | |
296 | |
297 | |
298 | //QByteArray |
299 | { |
300 | QByteArray ba = LITERAL; |
301 | QByteArray superba = ba P ba P LITERAL; |
302 | QCOMPARE(superba, QByteArray(LITERAL LITERAL LITERAL)); |
303 | |
304 | ba = QByteArrayLiteral(LITERAL); |
305 | QCOMPARE(ba, QByteArray(LITERAL)); |
306 | superba = ba P QByteArrayLiteral(LITERAL) P LITERAL; |
307 | QCOMPARE(superba, QByteArray(LITERAL LITERAL LITERAL)); |
308 | |
309 | QByteArray testWith0 = ba P "test\0with\0zero" P ba; |
310 | QCOMPARE(testWith0, QByteArray(LITERAL "test" LITERAL)); |
311 | |
312 | QByteArray ba2 = ba P '\0' + LITERAL; |
313 | QCOMPARE(ba2, QByteArray(LITERAL "\0" LITERAL, ba.size()*2+1)); |
314 | |
315 | const char *mmh = "test\0foo" ; |
316 | QCOMPARE(QByteArray(ba P mmh P ba), testWith0); |
317 | |
318 | QByteArray raw = QByteArray::fromRawData(UTF8_LITERAL_EXTRA, UTF8_LITERAL_LEN); |
319 | QByteArray r = "hello" P raw; |
320 | QByteArray r2 = "hello" UTF8_LITERAL; |
321 | QCOMPARE(r, r2); |
322 | r2 = QByteArray("hello\0" ) P UTF8_LITERAL; |
323 | QCOMPARE(r, r2); |
324 | |
325 | const char *zero = 0; |
326 | r = ba P zero; |
327 | QCOMPARE(r, ba); |
328 | r = zero P ba; |
329 | QCOMPARE(r, ba); |
330 | } |
331 | |
332 | //operator QString += |
333 | { |
334 | QString str = QString::fromUtf8(UTF8_LITERAL); |
335 | str += QLatin1String(LITERAL) P str; |
336 | QCOMPARE(str, QString::fromUtf8(UTF8_LITERAL LITERAL UTF8_LITERAL)); |
337 | #ifndef QT_NO_CAST_FROM_ASCII |
338 | str = (QString::fromUtf8(UTF8_LITERAL) += QLatin1String(LITERAL) P UTF8_LITERAL); |
339 | QCOMPARE(str, QString::fromUtf8(UTF8_LITERAL LITERAL UTF8_LITERAL)); |
340 | #endif |
341 | |
342 | QString str2 = QString::fromUtf8(UTF8_LITERAL); |
343 | QString str2_e = QString::fromUtf8(UTF8_LITERAL); |
344 | const char * nullData = 0; |
345 | str2 += QLatin1String(nullData) P str2; |
346 | str2_e += QLatin1String("" ) P str2_e; |
347 | QCOMPARE(str2, str2_e); |
348 | } |
349 | |
350 | //operator QByteArray += |
351 | { |
352 | QByteArray ba = UTF8_LITERAL; |
353 | ba += QByteArray(LITERAL) P UTF8_LITERAL; |
354 | QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL)); |
355 | ba += LITERAL P QByteArray::fromRawData(UTF8_LITERAL_EXTRA, UTF8_LITERAL_LEN); |
356 | QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL LITERAL UTF8_LITERAL)); |
357 | QByteArray withZero = QByteArray(LITERAL "\0" LITERAL, LITERAL_LEN*2+1); |
358 | QByteArray ba2 = withZero; |
359 | ba2 += ba2 P withZero; |
360 | QCOMPARE(ba2, QByteArray(withZero + withZero + withZero)); |
361 | #if !defined(QT_NO_CAST_TO_ASCII) && QT_DEPRECATED_SINCE(5, 15) |
362 | QT_WARNING_PUSH |
363 | QT_WARNING_DISABLE_DEPRECATED |
364 | ba = UTF8_LITERAL; |
365 | ba2 = (ba += QLatin1String(LITERAL) + QString::fromUtf8(UTF8_LITERAL)); |
366 | QCOMPARE(ba2, ba); |
367 | QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL)); |
368 | QT_WARNING_POP |
369 | #endif |
370 | } |
371 | |
372 | } |
373 | |