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#include <qchar.h>
31#include <qfile.h>
32#include <qstringlist.h>
33#include <private/qunicodetables_p.h>
34
35class tst_QChar : public QObject
36{
37 Q_OBJECT
38private slots:
39 void fromChar16_t();
40 void fromWchar_t();
41 void operator_eqeq_null();
42 void operators_data();
43 void operators();
44 void toUpper();
45 void toLower();
46 void toTitle();
47 void toCaseFolded();
48 void isDigit_data();
49 void isDigit();
50 void isLetter_data();
51 void isLetter();
52 void isLetterOrNumber_data();
53 void isLetterOrNumber();
54 void isPrint();
55 void isUpper();
56 void isLower();
57 void isTitleCase();
58 void isSpace_data();
59 void isSpace();
60 void isSpaceSpecial();
61 void category();
62 void direction();
63 void joiningType();
64 void combiningClass();
65 void digitValue();
66 void mirroredChar();
67 void decomposition();
68 void lineBreakClass();
69 void script();
70 void normalization_data();
71 void normalization();
72 void normalization_manual();
73 void normalizationCorrections();
74 void unicodeVersion();
75};
76
77QT_WARNING_PUSH
78QT_WARNING_DISABLE_DEPRECATED
79
80void tst_QChar::fromChar16_t()
81{
82#if defined(Q_COMPILER_UNICODE_STRINGS)
83 QChar aUmlaut = u'\u00E4'; // German small letter a-umlaut
84 QCOMPARE(aUmlaut, QChar(0xE4));
85 QChar replacementCharacter = u'\uFFFD';
86 QCOMPARE(replacementCharacter, QChar(QChar::ReplacementCharacter));
87#else
88 QSKIP("This test requires C++11 char16_t support enabled in the compiler.");
89#endif
90}
91
92void tst_QChar::fromWchar_t()
93{
94#if defined(Q_OS_WIN)
95 QChar aUmlaut = L'\u00E4'; // German small letter a-umlaut
96 QCOMPARE(aUmlaut, QChar(0xE4));
97 QChar replacementCharacter = L'\uFFFD';
98 QCOMPARE(replacementCharacter, QChar(QChar::ReplacementCharacter));
99#else
100 QSKIP("This is a Windows-only test.");
101#endif
102}
103
104void tst_QChar::operator_eqeq_null()
105{
106 {
107 const QChar ch = QLatin1Char(' ');
108#define CHECK(NUL) \
109 do { \
110 QVERIFY(!(ch == NUL)); \
111 QVERIFY( ch != NUL ); \
112 QVERIFY(!(ch < NUL)); \
113 QVERIFY( ch > NUL ); \
114 QVERIFY(!(ch <= NUL)); \
115 QVERIFY( ch >= NUL ); \
116 QVERIFY(!(NUL == ch )); \
117 QVERIFY( NUL != ch ); \
118 QVERIFY( NUL < ch ); \
119 QVERIFY(!(NUL > ch )); \
120 QVERIFY( NUL <= ch ); \
121 QVERIFY(!(NUL >= ch )); \
122 } while (0)
123
124 CHECK(0);
125 CHECK('\0');
126#undef CHECK
127 }
128 {
129 const QChar ch = QLatin1Char('\0');
130#define CHECK(NUL) \
131 do { \
132 QVERIFY( ch == NUL ); \
133 QVERIFY(!(ch != NUL)); \
134 QVERIFY(!(ch < NUL)); \
135 QVERIFY(!(ch > NUL)); \
136 QVERIFY( ch <= NUL ); \
137 QVERIFY( ch >= NUL ); \
138 QVERIFY( NUL == ch ); \
139 QVERIFY(!(NUL != ch )); \
140 QVERIFY(!(NUL < ch )); \
141 QVERIFY(!(NUL > ch )); \
142 QVERIFY( NUL <= ch ); \
143 QVERIFY( NUL >= ch ); \
144 } while (0)
145
146 CHECK(0);
147 CHECK('\0');
148#undef CHECK
149 }
150}
151
152void tst_QChar::operators_data()
153{
154 QTest::addColumn<QChar>(name: "lhs");
155 QTest::addColumn<QChar>(name: "rhs");
156
157 for (int i = 0; i < 3; ++i) {
158 for (int j = 0; j < 3; ++j)
159 QTest::addRow(format: "'\\%d' (op) '\\%d'", i, j)
160 << QChar(ushort(i)) << QChar(ushort(j));
161 }
162}
163
164void tst_QChar::operators()
165{
166 QFETCH(QChar, lhs);
167 QFETCH(QChar, rhs);
168
169#define CHECK(op) QCOMPARE((lhs op rhs), (lhs.unicode() op rhs.unicode()))
170 CHECK(==);
171 CHECK(!=);
172 CHECK(< );
173 CHECK(> );
174 CHECK(<=);
175 CHECK(>=);
176#undef CHECK
177}
178
179void tst_QChar::toUpper()
180{
181 QVERIFY(QChar('a').toUpper() == 'A');
182 QVERIFY(QChar('A').toUpper() == 'A');
183 QVERIFY(QChar(0x1c7).toUpper().unicode() == 0x1c7);
184 QVERIFY(QChar(0x1c8).toUpper().unicode() == 0x1c7);
185 QVERIFY(QChar(0x1c9).toUpper().unicode() == 0x1c7);
186 QVERIFY(QChar(0x25c).toUpper().unicode() == 0xa7ab);
187 QVERIFY(QChar(0x29e).toUpper().unicode() == 0xa7b0);
188 QVERIFY(QChar(0x1d79).toUpper().unicode() == 0xa77d);
189 QVERIFY(QChar(0x0265).toUpper().unicode() == 0xa78d);
190
191 QVERIFY(QChar::toUpper('a') == 'A');
192 QVERIFY(QChar::toUpper('A') == 'A');
193 QVERIFY(QChar::toUpper(0xdf) == 0xdf); // german sharp s
194 QVERIFY(QChar::toUpper(0x1c7) == 0x1c7);
195 QVERIFY(QChar::toUpper(0x1c8) == 0x1c7);
196 QVERIFY(QChar::toUpper(0x1c9) == 0x1c7);
197 QVERIFY(QChar::toUpper(0x25c) == 0xa7ab);
198 QVERIFY(QChar::toUpper(0x29e) == 0xa7b0);
199 QVERIFY(QChar::toUpper(0x1d79) == 0xa77d);
200 QVERIFY(QChar::toUpper(0x0265) == 0xa78d);
201
202 QVERIFY(QChar::toUpper(0x10400) == 0x10400);
203 QVERIFY(QChar::toUpper(0x10428) == 0x10400);
204}
205
206void tst_QChar::toLower()
207{
208 QVERIFY(QChar('A').toLower() == 'a');
209 QVERIFY(QChar('a').toLower() == 'a');
210 QVERIFY(QChar(0x1c7).toLower().unicode() == 0x1c9);
211 QVERIFY(QChar(0x1c8).toLower().unicode() == 0x1c9);
212 QVERIFY(QChar(0x1c9).toLower().unicode() == 0x1c9);
213 QVERIFY(QChar(0xa77d).toLower().unicode() == 0x1d79);
214 QVERIFY(QChar(0xa78d).toLower().unicode() == 0x0265);
215 QVERIFY(QChar(0xa7ab).toLower().unicode() == 0x25c);
216 QVERIFY(QChar(0xa7b1).toLower().unicode() == 0x287);
217
218 QVERIFY(QChar::toLower('a') == 'a');
219 QVERIFY(QChar::toLower('A') == 'a');
220 QVERIFY(QChar::toLower(0x1c7) == 0x1c9);
221 QVERIFY(QChar::toLower(0x1c8) == 0x1c9);
222 QVERIFY(QChar::toLower(0x1c9) == 0x1c9);
223 QVERIFY(QChar::toLower(0xa77d) == 0x1d79);
224 QVERIFY(QChar::toLower(0xa78d) == 0x0265);
225 QVERIFY(QChar::toLower(0xa7ab) == 0x25c);
226 QVERIFY(QChar::toLower(0xa7b1) == 0x287);
227
228 QVERIFY(QChar::toLower(0x10400) == 0x10428);
229 QVERIFY(QChar::toLower(0x10428) == 0x10428);
230}
231
232void tst_QChar::toTitle()
233{
234 QVERIFY(QChar('a').toTitleCase() == 'A');
235 QVERIFY(QChar('A').toTitleCase() == 'A');
236 QVERIFY(QChar(0x1c7).toTitleCase().unicode() == 0x1c8);
237 QVERIFY(QChar(0x1c8).toTitleCase().unicode() == 0x1c8);
238 QVERIFY(QChar(0x1c9).toTitleCase().unicode() == 0x1c8);
239 QVERIFY(QChar(0x1d79).toTitleCase().unicode() == 0xa77d);
240 QVERIFY(QChar(0x0265).toTitleCase().unicode() == 0xa78d);
241
242 QVERIFY(QChar::toTitleCase('a') == 'A');
243 QVERIFY(QChar::toTitleCase('A') == 'A');
244 QVERIFY(QChar::toTitleCase(0xdf) == 0xdf); // german sharp s
245 QVERIFY(QChar::toTitleCase(0x1c7) == 0x1c8);
246 QVERIFY(QChar::toTitleCase(0x1c8) == 0x1c8);
247 QVERIFY(QChar::toTitleCase(0x1c9) == 0x1c8);
248 QVERIFY(QChar::toTitleCase(0x1d79) == 0xa77d);
249 QVERIFY(QChar::toTitleCase(0x0265) == 0xa78d);
250
251 QVERIFY(QChar::toTitleCase(0x10400) == 0x10400);
252 QVERIFY(QChar::toTitleCase(0x10428) == 0x10400);
253}
254
255void tst_QChar::toCaseFolded()
256{
257 QVERIFY(QChar('a').toCaseFolded() == 'a');
258 QVERIFY(QChar('A').toCaseFolded() == 'a');
259 QVERIFY(QChar(0x1c7).toCaseFolded().unicode() == 0x1c9);
260 QVERIFY(QChar(0x1c8).toCaseFolded().unicode() == 0x1c9);
261 QVERIFY(QChar(0x1c9).toCaseFolded().unicode() == 0x1c9);
262 QVERIFY(QChar(0xa77d).toCaseFolded().unicode() == 0x1d79);
263 QVERIFY(QChar(0xa78d).toCaseFolded().unicode() == 0x0265);
264 QVERIFY(QChar(0xa7ab).toCaseFolded().unicode() == 0x25c);
265 QVERIFY(QChar(0xa7b1).toCaseFolded().unicode() == 0x287);
266
267 QVERIFY(QChar::toCaseFolded('a') == 'a');
268 QVERIFY(QChar::toCaseFolded('A') == 'a');
269 QVERIFY(QChar::toCaseFolded(0x1c7) == 0x1c9);
270 QVERIFY(QChar::toCaseFolded(0x1c8) == 0x1c9);
271 QVERIFY(QChar::toCaseFolded(0x1c9) == 0x1c9);
272 QVERIFY(QChar::toCaseFolded(0xa77d) == 0x1d79);
273 QVERIFY(QChar::toCaseFolded(0xa78d) == 0x0265);
274 QVERIFY(QChar::toCaseFolded(0xa7ab) == 0x25c);
275 QVERIFY(QChar::toCaseFolded(0xa7b1) == 0x287);
276
277 QVERIFY(QChar::toCaseFolded(0x10400) == 0x10428);
278 QVERIFY(QChar::toCaseFolded(0x10428) == 0x10428);
279
280 QVERIFY(QChar::toCaseFolded(0xb5) == 0x3bc);
281}
282
283void tst_QChar::isDigit_data()
284{
285 QTest::addColumn<ushort>(name: "ucs");
286 QTest::addColumn<bool>(name: "expected");
287
288 for (ushort ucs = 0; ucs < 256; ++ucs) {
289 bool isDigit = (ucs <= '9' && ucs >= '0');
290 const QByteArray tag = "0x" + QByteArray::number(ucs, base: 16);
291 QTest::newRow(dataTag: tag.constData()) << ucs << isDigit;
292 }
293}
294
295void tst_QChar::isDigit()
296{
297 QFETCH(ushort, ucs);
298 QFETCH(bool, expected);
299 QCOMPARE(QChar(ucs).isDigit(), expected);
300}
301
302static bool isExpectedLetter(ushort ucs)
303{
304 return (ucs >= 'a' && ucs <= 'z') || (ucs >= 'A' && ucs <= 'Z')
305 || ucs == 0xAA || ucs == 0xB5 || ucs == 0xBA
306 || (ucs >= 0xC0 && ucs <= 0xD6)
307 || (ucs >= 0xD8 && ucs <= 0xF6)
308 || (ucs >= 0xF8 && ucs <= 0xFF);
309}
310
311void tst_QChar::isLetter_data()
312{
313 QTest::addColumn<ushort>(name: "ucs");
314 QTest::addColumn<bool>(name: "expected");
315
316 for (ushort ucs = 0; ucs < 256; ++ucs) {
317 const QByteArray tag = "0x" + QByteArray::number(ucs, base: 16);
318 QTest::newRow(dataTag: tag.constData()) << ucs << isExpectedLetter(ucs);
319 }
320}
321
322void tst_QChar::isLetter()
323{
324 QFETCH(ushort, ucs);
325 QFETCH(bool, expected);
326 QCOMPARE(QChar(ucs).isLetter(), expected);
327}
328
329void tst_QChar::isLetterOrNumber_data()
330{
331 QTest::addColumn<ushort>(name: "ucs");
332 QTest::addColumn<bool>(name: "expected");
333
334 for (ushort ucs = 0; ucs < 256; ++ucs) {
335 bool isLetterOrNumber = isExpectedLetter(ucs)
336 || (ucs >= '0' && ucs <= '9')
337 || ucs == 0xB2 || ucs == 0xB3 || ucs == 0xB9
338 || (ucs >= 0xBC && ucs <= 0xBE);
339 const QByteArray tag = "0x" + QByteArray::number(ucs, base: 16);
340 QTest::newRow(dataTag: tag.constData()) << ucs << isLetterOrNumber;
341 }
342}
343
344void tst_QChar::isLetterOrNumber()
345{
346 QFETCH(ushort, ucs);
347 QFETCH(bool, expected);
348 QCOMPARE(QChar(ucs).isLetterOrNumber(), expected);
349}
350
351void tst_QChar::isPrint()
352{
353 // noncharacters, reserved (General_Gategory =Cn)
354 QVERIFY(!QChar(0x2064).isPrint());
355 QVERIFY(!QChar(0x2069).isPrint());
356 QVERIFY(!QChar(0xfdd0).isPrint());
357 QVERIFY(!QChar(0xfdef).isPrint());
358 QVERIFY(!QChar(0xfff0).isPrint());
359 QVERIFY(!QChar(0xfff8).isPrint());
360 QVERIFY(!QChar(0xfffe).isPrint());
361 QVERIFY(!QChar(0xffff).isPrint());
362 QVERIFY(!QChar::isPrint(0xe0000));
363 QVERIFY(!QChar::isPrint(0xe0002));
364 QVERIFY(!QChar::isPrint(0xe001f));
365 QVERIFY(!QChar::isPrint(0xe0080));
366 QVERIFY(!QChar::isPrint(0xe00ff));
367
368 // Other_Default_Ignorable_Code_Point, Variation_Selector
369 QVERIFY(QChar(0x034f).isPrint());
370 QVERIFY(QChar(0x115f).isPrint());
371 QVERIFY(QChar(0x180b).isPrint());
372 QVERIFY(QChar(0x180d).isPrint());
373 QVERIFY(QChar(0x3164).isPrint());
374 QVERIFY(QChar(0xfe00).isPrint());
375 QVERIFY(QChar(0xfe0f).isPrint());
376 QVERIFY(QChar(0xffa0).isPrint());
377 QVERIFY(QChar::isPrint(0xe0100));
378 QVERIFY(QChar::isPrint(0xe01ef));
379
380 // Cf, Cs, Cc, White_Space, Annotation Characters
381 QVERIFY(!QChar(0x0008).isPrint());
382 QVERIFY(!QChar(0x000a).isPrint());
383 QVERIFY(QChar(0x0020).isPrint());
384 QVERIFY(QChar(0x00a0).isPrint());
385 QVERIFY(!QChar(0x00ad).isPrint());
386 QVERIFY(!QChar(0x0085).isPrint());
387 QVERIFY(!QChar(0xd800).isPrint());
388 QVERIFY(!QChar(0xdc00).isPrint());
389 QVERIFY(!QChar(0xfeff).isPrint());
390 QVERIFY(!QChar::isPrint(0x1d173));
391
392 QVERIFY(QChar('0').isPrint());
393 QVERIFY(QChar('A').isPrint());
394 QVERIFY(QChar('a').isPrint());
395
396 QVERIFY(QChar(0x0370).isPrint()); // assigned in 5.1
397 QVERIFY(QChar(0x0524).isPrint()); // assigned in 5.2
398 QVERIFY(QChar(0x0526).isPrint()); // assigned in 6.0
399 QVERIFY(QChar(0x08a0).isPrint()); // assigned in 6.1
400 QVERIFY(!QChar(0x1aff).isPrint()); // not assigned
401 QVERIFY(QChar(0x1e9e).isPrint()); // assigned in 5.1
402 QVERIFY(QChar::isPrint(0x1b000)); // assigned in 6.0
403 QVERIFY(QChar::isPrint(0x110d0)); // assigned in 5.1
404 QVERIFY(!QChar::isPrint(0x1bca0)); // assigned in 7.0
405}
406
407void tst_QChar::isUpper()
408{
409 QVERIFY(QChar('A').isUpper());
410 QVERIFY(QChar('Z').isUpper());
411 QVERIFY(!QChar('a').isUpper());
412 QVERIFY(!QChar('z').isUpper());
413 QVERIFY(!QChar('?').isUpper());
414 QVERIFY(QChar(0xC2).isUpper()); // A with ^
415 QVERIFY(!QChar(0xE2).isUpper()); // a with ^
416
417 for (uint codepoint = 0; codepoint <= QChar::LastValidCodePoint; ++codepoint) {
418 if (QChar::isUpper(ucs4: codepoint))
419 QVERIFY(codepoint == QChar::toUpper(codepoint));
420 }
421}
422
423void tst_QChar::isLower()
424{
425 QVERIFY(!QChar('A').isLower());
426 QVERIFY(!QChar('Z').isLower());
427 QVERIFY(QChar('a').isLower());
428 QVERIFY(QChar('z').isLower());
429 QVERIFY(!QChar('?').isLower());
430 QVERIFY(!QChar(0xC2).isLower()); // A with ^
431 QVERIFY(QChar(0xE2).isLower()); // a with ^
432
433 for (uint codepoint = 0; codepoint <= QChar::LastValidCodePoint; ++codepoint) {
434 if (QChar::isLower(ucs4: codepoint))
435 QVERIFY(codepoint == QChar::toLower(codepoint));
436 }
437}
438
439void tst_QChar::isTitleCase()
440{
441 for (uint codepoint = 0; codepoint <= QChar::LastValidCodePoint; ++codepoint) {
442 if (QChar::isTitleCase(ucs4: codepoint))
443 QVERIFY(codepoint == QChar::toTitleCase(codepoint));
444 }
445}
446
447void tst_QChar::isSpace_data()
448{
449 QTest::addColumn<ushort>(name: "ucs");
450 QTest::addColumn<bool>(name: "expected");
451
452 for (ushort ucs = 0; ucs < 256; ++ucs) {
453 bool isSpace = (ucs <= 0x0D && ucs >= 0x09) || ucs == 0x20 || ucs == 0xA0 || ucs == 0x85;
454 const QByteArray tag = "0x" + QByteArray::number(ucs, base: 16);
455 QTest::newRow(dataTag: tag.constData()) << ucs << isSpace;
456 }
457}
458
459void tst_QChar::isSpace()
460{
461 QFETCH(ushort, ucs);
462 QFETCH(bool, expected);
463 QCOMPARE(QChar(ucs).isSpace(), expected);
464}
465
466void tst_QChar::isSpaceSpecial()
467{
468 QVERIFY(!QChar(QChar::Null).isSpace());
469 QVERIFY(QChar(QChar::Nbsp).isSpace());
470 QVERIFY(QChar(QChar::ParagraphSeparator).isSpace());
471 QVERIFY(QChar(QChar::LineSeparator).isSpace());
472 QVERIFY(QChar(0x1680).isSpace());
473}
474
475void tst_QChar::category()
476{
477 QVERIFY(QChar('a').category() == QChar::Letter_Lowercase);
478 QVERIFY(QChar('A').category() == QChar::Letter_Uppercase);
479
480 QVERIFY(QChar::category('a') == QChar::Letter_Lowercase);
481 QVERIFY(QChar::category('A') == QChar::Letter_Uppercase);
482
483 QVERIFY(QChar::category(0xe0100) == QChar::Mark_NonSpacing);
484 QVERIFY(QChar::category(0xeffff) != QChar::Other_PrivateUse);
485 QVERIFY(QChar::category(0xf0000) == QChar::Other_PrivateUse);
486 QVERIFY(QChar::category(0xf0001) == QChar::Other_PrivateUse);
487
488 QVERIFY(QChar::category(0xd900) == QChar::Other_Surrogate);
489 QVERIFY(QChar::category(0xdc00) == QChar::Other_Surrogate);
490 QVERIFY(QChar::category(0xdc01) == QChar::Other_Surrogate);
491
492 QVERIFY(QChar::category(0x1aff) == QChar::Other_NotAssigned);
493 QVERIFY(QChar::category(0x10fffd) == QChar::Other_PrivateUse);
494 QVERIFY(QChar::category(0x10ffff) == QChar::Other_NotAssigned);
495 QVERIFY(QChar::category(0x110000) == QChar::Other_NotAssigned);
496}
497
498void tst_QChar::direction()
499{
500 QVERIFY(QChar::direction(0x200E) == QChar::DirL);
501 QVERIFY(QChar::direction(0x200F) == QChar::DirR);
502 QVERIFY(QChar::direction(0x202A) == QChar::DirLRE);
503 QVERIFY(QChar::direction(0x202B) == QChar::DirRLE);
504 QVERIFY(QChar::direction(0x202C) == QChar::DirPDF);
505 QVERIFY(QChar::direction(0x202D) == QChar::DirLRO);
506 QVERIFY(QChar::direction(0x202E) == QChar::DirRLO);
507 QVERIFY(QChar::direction(0x2066) == QChar::DirLRI);
508 QVERIFY(QChar::direction(0x2067) == QChar::DirRLI);
509 QVERIFY(QChar::direction(0x2068) == QChar::DirFSI);
510 QVERIFY(QChar::direction(0x2069) == QChar::DirPDI);
511
512 QVERIFY(QChar('a').direction() == QChar::DirL);
513 QVERIFY(QChar('0').direction() == QChar::DirEN);
514 QVERIFY(QChar(0x627).direction() == QChar::DirAL);
515 QVERIFY(QChar(0x5d0).direction() == QChar::DirR);
516
517 QVERIFY(QChar::direction('a') == QChar::DirL);
518 QVERIFY(QChar::direction('0') == QChar::DirEN);
519 QVERIFY(QChar::direction(0x627) == QChar::DirAL);
520 QVERIFY(QChar::direction(0x5d0) == QChar::DirR);
521
522 QVERIFY(QChar::direction(0xE01DA) == QChar::DirNSM);
523 QVERIFY(QChar::direction(0xf0000) == QChar::DirL);
524 QVERIFY(QChar::direction(0xE0030) == QChar::DirBN);
525 QVERIFY(QChar::direction(0x2FA17) == QChar::DirL);
526}
527
528void tst_QChar::joiningType()
529{
530 QVERIFY(QChar('a').joiningType() == QChar::Joining_None);
531 QVERIFY(QChar('0').joiningType() == QChar::Joining_None);
532 QVERIFY(QChar(0x0627).joiningType() == QChar::Joining_Right);
533 QVERIFY(QChar(0x05d0).joiningType() == QChar::Joining_None);
534 QVERIFY(QChar(0x00ad).joiningType() == QChar::Joining_Transparent);
535 QVERIFY(QChar(0xA872).joiningType() == QChar::Joining_Left);
536
537 QVERIFY(QChar::joiningType('a') == QChar::Joining_None);
538 QVERIFY(QChar::joiningType('0') == QChar::Joining_None);
539 QVERIFY(QChar::joiningType(0x0627) == QChar::Joining_Right);
540 QVERIFY(QChar::joiningType(0x05d0) == QChar::Joining_None);
541 QVERIFY(QChar::joiningType(0x00ad) == QChar::Joining_Transparent);
542
543 QVERIFY(QChar::joiningType(0xE01DA) == QChar::Joining_Transparent);
544 QVERIFY(QChar::joiningType(0xf0000) == QChar::Joining_None);
545 QVERIFY(QChar::joiningType(0xE0030) == QChar::Joining_Transparent);
546 QVERIFY(QChar::joiningType(0x2FA17) == QChar::Joining_None);
547
548 QVERIFY(QChar::joiningType(0xA872) == QChar::Joining_Left);
549 QVERIFY(QChar::joiningType(0x10ACD) == QChar::Joining_Left);
550 QVERIFY(QChar::joiningType(0x10AD7) == QChar::Joining_Left);
551}
552
553void tst_QChar::combiningClass()
554{
555 QVERIFY(QChar('a').combiningClass() == 0);
556 QVERIFY(QChar('0').combiningClass() == 0);
557 QVERIFY(QChar(0x627).combiningClass() == 0);
558 QVERIFY(QChar(0x5d0).combiningClass() == 0);
559
560 QVERIFY(QChar::combiningClass('a') == 0);
561 QVERIFY(QChar::combiningClass('0') == 0);
562 QVERIFY(QChar::combiningClass(0x627) == 0);
563 QVERIFY(QChar::combiningClass(0x5d0) == 0);
564
565 QVERIFY(QChar::combiningClass(0xE01DA) == 0);
566 QVERIFY(QChar::combiningClass(0xf0000) == 0);
567 QVERIFY(QChar::combiningClass(0xE0030) == 0);
568 QVERIFY(QChar::combiningClass(0x2FA17) == 0);
569
570 QVERIFY(QChar::combiningClass(0x300) == 230);
571
572 QVERIFY(QChar::combiningClass(0x1d244) == 230);
573
574}
575
576void tst_QChar::unicodeVersion()
577{
578 QVERIFY(QChar('a').unicodeVersion() == QChar::Unicode_1_1);
579 QVERIFY(QChar('0').unicodeVersion() == QChar::Unicode_1_1);
580 QVERIFY(QChar(0x627).unicodeVersion() == QChar::Unicode_1_1);
581 QVERIFY(QChar(0x5d0).unicodeVersion() == QChar::Unicode_1_1);
582
583 QVERIFY(QChar::unicodeVersion('a') == QChar::Unicode_1_1);
584 QVERIFY(QChar::unicodeVersion('0') == QChar::Unicode_1_1);
585 QVERIFY(QChar::unicodeVersion(0x627) == QChar::Unicode_1_1);
586 QVERIFY(QChar::unicodeVersion(0x5d0) == QChar::Unicode_1_1);
587
588 QVERIFY(QChar(0x0591).unicodeVersion() == QChar::Unicode_2_0);
589 QVERIFY(QChar::unicodeVersion(0x0591) == QChar::Unicode_2_0);
590
591 QVERIFY(QChar(0x20AC).unicodeVersion() == QChar::Unicode_2_1_2);
592 QVERIFY(QChar::unicodeVersion(0x20AC) == QChar::Unicode_2_1_2);
593 QVERIFY(QChar(0xfffc).unicodeVersion() == QChar::Unicode_2_1_2);
594 QVERIFY(QChar::unicodeVersion(0xfffc) == QChar::Unicode_2_1_2);
595
596 QVERIFY(QChar(0x01f6).unicodeVersion() == QChar::Unicode_3_0);
597 QVERIFY(QChar::unicodeVersion(0x01f6) == QChar::Unicode_3_0);
598
599 QVERIFY(QChar(0x03F4).unicodeVersion() == QChar::Unicode_3_1);
600 QVERIFY(QChar::unicodeVersion(0x03F4) == QChar::Unicode_3_1);
601 QVERIFY(QChar::unicodeVersion(0x10300) == QChar::Unicode_3_1);
602
603 QVERIFY(QChar(0x0220).unicodeVersion() == QChar::Unicode_3_2);
604 QVERIFY(QChar::unicodeVersion(0x0220) == QChar::Unicode_3_2);
605 QVERIFY(QChar::unicodeVersion(0xFF5F) == QChar::Unicode_3_2);
606
607 QVERIFY(QChar(0x0221).unicodeVersion() == QChar::Unicode_4_0);
608 QVERIFY(QChar::unicodeVersion(0x0221) == QChar::Unicode_4_0);
609 QVERIFY(QChar::unicodeVersion(0x10000) == QChar::Unicode_4_0);
610
611 QVERIFY(QChar(0x0237).unicodeVersion() == QChar::Unicode_4_1);
612 QVERIFY(QChar::unicodeVersion(0x0237) == QChar::Unicode_4_1);
613 QVERIFY(QChar::unicodeVersion(0x10140) == QChar::Unicode_4_1);
614
615 QVERIFY(QChar(0x0242).unicodeVersion() == QChar::Unicode_5_0);
616 QVERIFY(QChar::unicodeVersion(0x0242) == QChar::Unicode_5_0);
617 QVERIFY(QChar::unicodeVersion(0x12000) == QChar::Unicode_5_0);
618
619 QVERIFY(QChar(0x0370).unicodeVersion() == QChar::Unicode_5_1);
620 QVERIFY(QChar::unicodeVersion(0x0370) == QChar::Unicode_5_1);
621 QVERIFY(QChar::unicodeVersion(0x1f093) == QChar::Unicode_5_1);
622
623 QVERIFY(QChar(0x0524).unicodeVersion() == QChar::Unicode_5_2);
624 QVERIFY(QChar::unicodeVersion(0x0524) == QChar::Unicode_5_2);
625 QVERIFY(QChar::unicodeVersion(0x2b734) == QChar::Unicode_5_2);
626
627 QVERIFY(QChar(0x26ce).unicodeVersion() == QChar::Unicode_6_0);
628 QVERIFY(QChar::unicodeVersion(0x26ce) == QChar::Unicode_6_0);
629 QVERIFY(QChar::unicodeVersion(0x1f618) == QChar::Unicode_6_0);
630
631 QVERIFY(QChar(0xa69f).unicodeVersion() == QChar::Unicode_6_1);
632 QVERIFY(QChar::unicodeVersion(0xa69f) == QChar::Unicode_6_1);
633 QVERIFY(QChar::unicodeVersion(0x1f600) == QChar::Unicode_6_1);
634
635 QVERIFY(QChar(0x20ba).unicodeVersion() == QChar::Unicode_6_2);
636 QVERIFY(QChar::unicodeVersion(0x20ba) == QChar::Unicode_6_2);
637
638 QVERIFY(QChar(0x061c).unicodeVersion() == QChar::Unicode_6_3);
639 QVERIFY(QChar::unicodeVersion(0x061c) == QChar::Unicode_6_3);
640
641 QVERIFY(QChar(0x20bd).unicodeVersion() == QChar::Unicode_7_0);
642 QVERIFY(QChar::unicodeVersion(0x20bd) == QChar::Unicode_7_0);
643 QVERIFY(QChar::unicodeVersion(0x16b00) == QChar::Unicode_7_0);
644
645 QVERIFY(QChar(0x08b3).unicodeVersion() == QChar::Unicode_8_0);
646 QVERIFY(QChar::unicodeVersion(0x08b3) == QChar::Unicode_8_0);
647 QVERIFY(QChar::unicodeVersion(0x108e0) == QChar::Unicode_8_0);
648
649 QVERIFY(QChar(0x09ff).unicodeVersion() == QChar::Unicode_Unassigned);
650 QVERIFY(QChar::unicodeVersion(0x09ff) == QChar::Unicode_Unassigned);
651 QVERIFY(QChar::unicodeVersion(0x110000) == QChar::Unicode_Unassigned);
652}
653
654void tst_QChar::digitValue()
655{
656 QVERIFY(QChar('9').digitValue() == 9);
657 QVERIFY(QChar('0').digitValue() == 0);
658 QVERIFY(QChar('a').digitValue() == -1);
659
660 QVERIFY(QChar::digitValue('9') == 9);
661 QVERIFY(QChar::digitValue('0') == 0);
662
663 QVERIFY(QChar::digitValue(0x1049) == 9);
664 QVERIFY(QChar::digitValue(0x1040) == 0);
665
666 QVERIFY(QChar::digitValue(0xd800) == -1);
667 QVERIFY(QChar::digitValue(0x110000) == -1);
668}
669
670void tst_QChar::mirroredChar()
671{
672 QVERIFY(QChar(0x169B).hasMirrored());
673 QVERIFY(QChar(0x169B).mirroredChar() == QChar(0x169C));
674 QVERIFY(QChar(0x169C).hasMirrored());
675 QVERIFY(QChar(0x169C).mirroredChar() == QChar(0x169B));
676
677 QVERIFY(QChar(0x301A).hasMirrored());
678 QVERIFY(QChar(0x301A).mirroredChar() == QChar(0x301B));
679 QVERIFY(QChar(0x301B).hasMirrored());
680 QVERIFY(QChar(0x301B).mirroredChar() == QChar(0x301A));
681}
682
683void tst_QChar::decomposition()
684{
685 // Hangul syllables
686 for (uint ucs = 0xac00; ucs <= 0xd7af; ++ucs) {
687 QChar::Decomposition expected = QChar::unicodeVersion(ucs4: ucs) > QChar::Unicode_Unassigned ? QChar::Canonical : QChar::NoDecomposition;
688 QString desc = QString::fromLatin1(str: "ucs = 0x%1, tag = %2, expected = %3")
689 .arg(a: QString::number(ucs, base: 16)).arg(a: QChar::decompositionTag(ucs4: ucs)).arg(a: expected);
690 QVERIFY2(QChar::decompositionTag(ucs) == expected, desc.toLatin1());
691 }
692
693 QVERIFY(QChar(0xa0).decompositionTag() == QChar::NoBreak);
694 QVERIFY(QChar(0xa8).decompositionTag() == QChar::Compat);
695 QVERIFY(QChar(0x41).decompositionTag() == QChar::NoDecomposition);
696
697 QVERIFY(QChar::decompositionTag(0xa0) == QChar::NoBreak);
698 QVERIFY(QChar::decompositionTag(0xa8) == QChar::Compat);
699 QVERIFY(QChar::decompositionTag(0x41) == QChar::NoDecomposition);
700
701 QVERIFY(QChar::decomposition(0xa0) == QString(QChar(0x20)));
702 QVERIFY(QChar::decomposition(0xc0) == (QString(QChar(0x41)) + QString(QChar(0x300))));
703
704 {
705 QString str;
706 str += QChar(QChar::highSurrogate(ucs4: 0x1D157));
707 str += QChar(QChar::lowSurrogate(ucs4: 0x1D157));
708 str += QChar(QChar::highSurrogate(ucs4: 0x1D165));
709 str += QChar(QChar::lowSurrogate(ucs4: 0x1D165));
710 QVERIFY(QChar::decomposition(0x1D15e) == str);
711 }
712
713 {
714 QString str;
715 str += QChar(0x1100);
716 str += QChar(0x1161);
717 QVERIFY(QChar::decomposition(0xac00) == str);
718 }
719 {
720 QString str;
721 str += QChar(0x110c);
722 str += QChar(0x1165);
723 str += QChar(0x11b7);
724 QVERIFY(QChar::decomposition(0xc810) == str);
725 }
726}
727
728void tst_QChar::lineBreakClass()
729{
730 QVERIFY(QUnicodeTables::lineBreakClass(0x0029) == QUnicodeTables::LineBreak_CP);
731 QVERIFY(QUnicodeTables::lineBreakClass(0x0041) == QUnicodeTables::LineBreak_AL);
732 QVERIFY(QUnicodeTables::lineBreakClass(0x0033) == QUnicodeTables::LineBreak_NU);
733 QVERIFY(QUnicodeTables::lineBreakClass(0x00ad) == QUnicodeTables::LineBreak_BA);
734 QVERIFY(QUnicodeTables::lineBreakClass(0x05d0) == QUnicodeTables::LineBreak_HL);
735 QVERIFY(QUnicodeTables::lineBreakClass(0xfffc) == QUnicodeTables::LineBreak_CB);
736 QVERIFY(QUnicodeTables::lineBreakClass(0xe0164) == QUnicodeTables::LineBreak_CM);
737 QVERIFY(QUnicodeTables::lineBreakClass(0x2f9a4) == QUnicodeTables::LineBreak_ID);
738 QVERIFY(QUnicodeTables::lineBreakClass(0x10000) == QUnicodeTables::LineBreak_AL);
739 QVERIFY(QUnicodeTables::lineBreakClass(0x1f1e6) == QUnicodeTables::LineBreak_RI);
740
741 // mapped to AL:
742 QVERIFY(QUnicodeTables::lineBreakClass(0xfffd) == QUnicodeTables::LineBreak_AL); // AI -> AL
743 QVERIFY(QUnicodeTables::lineBreakClass(0x100000) == QUnicodeTables::LineBreak_AL); // XX -> AL
744}
745
746void tst_QChar::script()
747{
748 QVERIFY(QChar::script(0x0020) == QChar::Script_Common);
749 QVERIFY(QChar::script(0x0041) == QChar::Script_Latin);
750 QVERIFY(QChar::script(0x0375) == QChar::Script_Greek);
751 QVERIFY(QChar::script(0x0400) == QChar::Script_Cyrillic);
752 QVERIFY(QChar::script(0x0531) == QChar::Script_Armenian);
753 QVERIFY(QChar::script(0x0591) == QChar::Script_Hebrew);
754 QVERIFY(QChar::script(0x0600) == QChar::Script_Arabic);
755 QVERIFY(QChar::script(0x0700) == QChar::Script_Syriac);
756 QVERIFY(QChar::script(0x0780) == QChar::Script_Thaana);
757 QVERIFY(QChar::script(0x07c0) == QChar::Script_Nko);
758 QVERIFY(QChar::script(0x0900) == QChar::Script_Devanagari);
759 QVERIFY(QChar::script(0x0981) == QChar::Script_Bengali);
760 QVERIFY(QChar::script(0x0a01) == QChar::Script_Gurmukhi);
761 QVERIFY(QChar::script(0x0a81) == QChar::Script_Gujarati);
762 QVERIFY(QChar::script(0x0b01) == QChar::Script_Oriya);
763 QVERIFY(QChar::script(0x0b82) == QChar::Script_Tamil);
764 QVERIFY(QChar::script(0x0c01) == QChar::Script_Telugu);
765 QVERIFY(QChar::script(0x0c82) == QChar::Script_Kannada);
766 QVERIFY(QChar::script(0x0d02) == QChar::Script_Malayalam);
767 QVERIFY(QChar::script(0x0d82) == QChar::Script_Sinhala);
768 QVERIFY(QChar::script(0x0e01) == QChar::Script_Thai);
769 QVERIFY(QChar::script(0x0e81) == QChar::Script_Lao);
770 QVERIFY(QChar::script(0x0f00) == QChar::Script_Tibetan);
771 QVERIFY(QChar::script(0x1000) == QChar::Script_Myanmar);
772 QVERIFY(QChar::script(0x10a0) == QChar::Script_Georgian);
773 QVERIFY(QChar::script(0x1100) == QChar::Script_Hangul);
774 QVERIFY(QChar::script(0x1680) == QChar::Script_Ogham);
775 QVERIFY(QChar::script(0x16a0) == QChar::Script_Runic);
776 QVERIFY(QChar::script(0x1780) == QChar::Script_Khmer);
777 QVERIFY(QChar::script(0x200c) == QChar::Script_Inherited);
778 QVERIFY(QChar::script(0x200d) == QChar::Script_Inherited);
779 QVERIFY(QChar::script(0x1018a) == QChar::Script_Greek);
780 QVERIFY(QChar::script(0x1f130) == QChar::Script_Common);
781 QVERIFY(QChar::script(0xe0100) == QChar::Script_Inherited);
782}
783
784void tst_QChar::normalization_data()
785{
786 QTest::addColumn<QStringList>(name: "columns");
787 QTest::addColumn<int>(name: "part");
788
789 int linenum = 0;
790 int part = 0;
791
792 QString testFile = QFINDTESTDATA("data/NormalizationTest.txt");
793 QVERIFY2(!testFile.isEmpty(), "data/NormalizationTest.txt not found!");
794 QFile f(testFile);
795 QVERIFY(f.exists());
796
797 f.open(flags: QIODevice::ReadOnly);
798
799 while (!f.atEnd()) {
800 linenum++;
801
802 QByteArray line;
803 line.resize(size: 1024);
804 int len = f.readLine(data: line.data(), maxlen: 1024);
805 line.resize(size: len-1);
806
807 int comment = line.indexOf(c: '#');
808 if (comment >= 0)
809 line = line.left(len: comment);
810
811 if (line.startsWith(c: '@')) {
812 if (line.startsWith(c: "@Part") && line.size() > 5 && QChar(line.at(i: 5)).isDigit())
813 part = QChar(line.at(i: 5)).digitValue();
814 continue;
815 }
816
817 if (line.isEmpty())
818 continue;
819
820 line = line.trimmed();
821 if (line.endsWith(c: ';'))
822 line.truncate(pos: line.length()-1);
823
824 QList<QByteArray> l = line.split(sep: ';');
825
826 QCOMPARE(l.size(), 5);
827
828 QStringList columns;
829 for (int i = 0; i < 5; ++i) {
830 columns.append(t: QString());
831
832 QList<QByteArray> c = l.at(i).split(sep: ' ');
833 QVERIFY(!c.isEmpty());
834
835 for (int j = 0; j < c.size(); ++j) {
836 bool ok;
837 uint uc = c.at(i: j).toInt(ok: &ok, base: 16);
838 if (!QChar::requiresSurrogates(ucs4: uc)) {
839 columns[i].append(c: QChar(uc));
840 } else {
841 // convert to utf16
842 columns[i].append(c: QChar(QChar::highSurrogate(ucs4: uc)));
843 columns[i].append(c: QChar(QChar::lowSurrogate(ucs4: uc)));
844 }
845 }
846 }
847
848
849 const QByteArray nm = "line #" + QByteArray::number(linenum) + " (part "
850 + QByteArray::number(part);
851 QTest::newRow(dataTag: nm.constData()) << columns << part;
852 }
853}
854
855void tst_QChar::normalization()
856{
857 QFETCH(QStringList, columns);
858 QFETCH(int, part);
859
860 Q_UNUSED(part)
861
862 // CONFORMANCE:
863 // 1. The following invariants must be true for all conformant implementations
864 //
865 // NFC
866 // c2 == NFC(c1) == NFC(c2) == NFC(c3)
867 // c4 == NFC(c4) == NFC(c5)
868
869 QVERIFY(columns[1] == columns[0].normalized(QString::NormalizationForm_C));
870 QVERIFY(columns[1] == columns[1].normalized(QString::NormalizationForm_C));
871 QVERIFY(columns[1] == columns[2].normalized(QString::NormalizationForm_C));
872 QVERIFY(columns[3] == columns[3].normalized(QString::NormalizationForm_C));
873 QVERIFY(columns[3] == columns[4].normalized(QString::NormalizationForm_C));
874
875 // NFD
876 // c3 == NFD(c1) == NFD(c2) == NFD(c3)
877 // c5 == NFD(c4) == NFD(c5)
878
879 QVERIFY(columns[2] == columns[0].normalized(QString::NormalizationForm_D));
880 QVERIFY(columns[2] == columns[1].normalized(QString::NormalizationForm_D));
881 QVERIFY(columns[2] == columns[2].normalized(QString::NormalizationForm_D));
882 QVERIFY(columns[4] == columns[3].normalized(QString::NormalizationForm_D));
883 QVERIFY(columns[4] == columns[4].normalized(QString::NormalizationForm_D));
884
885 // NFKC
886 // c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
887
888 QVERIFY(columns[3] == columns[0].normalized(QString::NormalizationForm_KC));
889 QVERIFY(columns[3] == columns[1].normalized(QString::NormalizationForm_KC));
890 QVERIFY(columns[3] == columns[2].normalized(QString::NormalizationForm_KC));
891 QVERIFY(columns[3] == columns[3].normalized(QString::NormalizationForm_KC));
892 QVERIFY(columns[3] == columns[4].normalized(QString::NormalizationForm_KC));
893
894 // NFKD
895 // c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
896
897 QVERIFY(columns[4] == columns[0].normalized(QString::NormalizationForm_KD));
898 QVERIFY(columns[4] == columns[1].normalized(QString::NormalizationForm_KD));
899 QVERIFY(columns[4] == columns[2].normalized(QString::NormalizationForm_KD));
900 QVERIFY(columns[4] == columns[3].normalized(QString::NormalizationForm_KD));
901 QVERIFY(columns[4] == columns[4].normalized(QString::NormalizationForm_KD));
902
903 // 2. For every code point X assigned in this version of Unicode that is not specifically
904 // listed in Part 1, the following invariants must be true for all conformant
905 // implementations:
906 //
907 // X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
908
909 // #################
910
911}
912
913void tst_QChar::normalization_manual()
914{
915 {
916 QString decomposed;
917 decomposed += QChar(0x41);
918 decomposed += QChar(0x0221); // assigned in 4.0
919 decomposed += QChar(0x300);
920
921 QVERIFY(decomposed.normalized(QString::NormalizationForm_C, QChar::Unicode_3_2) == decomposed);
922
923 decomposed[1] = QChar(0x037f); // unassigned in 6.1
924
925 QVERIFY(decomposed.normalized(QString::NormalizationForm_C) == decomposed);
926 }
927 {
928 QString composed;
929 composed += QChar(0xc0);
930 QString decomposed;
931 decomposed += QChar(0x41);
932 decomposed += QChar(0x300);
933
934 QVERIFY(composed.normalized(QString::NormalizationForm_D) == decomposed);
935 QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
936 QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
937 QVERIFY(composed.normalized(QString::NormalizationForm_KC) == composed);
938 }
939 {
940 QString composed;
941 composed += QChar(0xa0);
942 QString decomposed;
943 decomposed += QChar(0x20);
944
945 QVERIFY(composed.normalized(QString::NormalizationForm_D) == composed);
946 QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
947 QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
948 QVERIFY(composed.normalized(QString::NormalizationForm_KC) == decomposed);
949 }
950 {
951 QString composed;
952 composed += QChar(0x0061);
953 composed += QChar(0x00f2);
954 QString decomposed;
955 decomposed += QChar(0x0061);
956 decomposed += QChar(0x006f);
957 decomposed += QChar(0x0300);
958
959 QVERIFY(decomposed.normalized(QString::NormalizationForm_D) == decomposed);
960 QVERIFY(decomposed.normalized(QString::NormalizationForm_C) == composed);
961 QVERIFY(decomposed.normalized(QString::NormalizationForm_KD) == decomposed);
962 QVERIFY(decomposed.normalized(QString::NormalizationForm_KC) == composed);
963 }
964 { // hangul
965 QString composed;
966 composed += QChar(0xc154);
967 composed += QChar(0x11f0);
968 QString decomposed;
969 decomposed += QChar(0x1109);
970 decomposed += QChar(0x1167);
971 decomposed += QChar(0x11f0);
972
973 QVERIFY(composed.normalized(QString::NormalizationForm_D) == decomposed);
974 QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
975 QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
976 QVERIFY(composed.normalized(QString::NormalizationForm_KC) == composed);
977
978 QVERIFY(decomposed.normalized(QString::NormalizationForm_D) == decomposed);
979 QVERIFY(decomposed.normalized(QString::NormalizationForm_C) == composed);
980 QVERIFY(decomposed.normalized(QString::NormalizationForm_KD) == decomposed);
981 QVERIFY(decomposed.normalized(QString::NormalizationForm_KC) == composed);
982 }
983 // QTBUG-71894 - erratum fixed in Unicode 4.1.0; SCount bounds are < not <=
984 {
985 // Hangul compose, test 0x11a7:
986 const QChar c[] = { QChar(0xae30), QChar(0x11a7), {} };
987 const QChar d[] = { QChar(0x1100), QChar(0x1175), QChar(0x11a7), {} };
988 const QString composed(c, 2);
989 const QString decomposed(d, 3);
990
991 QCOMPARE(decomposed.normalized(QString::NormalizationForm_C), composed);
992 }
993 {
994 // Hangul compose, test 0x11c3:
995 const QChar c[] = { QChar(0xae30), QChar(0x11c3), {} };
996 const QChar d[] = { QChar(0x1100), QChar(0x1175), QChar(0x11c3), {} };
997 const QString composed(c, 2);
998 const QString decomposed(d, 3);
999
1000 QCOMPARE(decomposed.normalized(QString::NormalizationForm_C), composed);
1001 }
1002}
1003
1004void tst_QChar::normalizationCorrections()
1005{
1006 QString s;
1007 s.append(c: QChar(0xf951));
1008
1009 QString n = s.normalized(mode: QString::NormalizationForm_D);
1010 QString res;
1011 res.append(c: QChar(0x964b));
1012 QCOMPARE(n, res);
1013
1014 n = s.normalized(mode: QString::NormalizationForm_D, version: QChar::Unicode_3_1);
1015 res.clear();
1016 res.append(c: QChar(0x96fb));
1017 QCOMPARE(n, res);
1018
1019 s.clear();
1020 s += QChar(QChar::highSurrogate(ucs4: 0x2f868));
1021 s += QChar(QChar::lowSurrogate(ucs4: 0x2f868));
1022
1023 n = s.normalized(mode: QString::NormalizationForm_C);
1024 res.clear();
1025 res += QChar(0x36fc);
1026 QCOMPARE(n, res);
1027
1028 n = s.normalized(mode: QString::NormalizationForm_C, version: QChar::Unicode_3_1);
1029 res.clear();
1030 res += QChar(0xd844);
1031 res += QChar(0xdf6a);
1032 QCOMPARE(n, res);
1033
1034 n = s.normalized(mode: QString::NormalizationForm_C, version: QChar::Unicode_3_2);
1035 QCOMPARE(n, res);
1036}
1037
1038
1039QTEST_APPLESS_MAIN(tst_QChar)
1040#include "tst_qchar.moc"
1041

source code of qtbase/tests/auto/corelib/text/qchar/tst_qchar.cpp