1/****************************************************************************
2**
3** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module 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 <QStringView>
30#include <QString>
31#include <QChar>
32#include <QStringRef>
33
34#include <QTest>
35
36#include <string>
37
38template <typename T>
39using CanConvert = std::is_convertible<T, QStringView>;
40
41Q_STATIC_ASSERT(!CanConvert<QLatin1String>::value);
42Q_STATIC_ASSERT(!CanConvert<const char*>::value);
43Q_STATIC_ASSERT(!CanConvert<QByteArray>::value);
44
45// QStringView qchar_does_not_compile() { return QStringView(QChar('a')); }
46// QStringView qlatin1string_does_not_compile() { return QStringView(QLatin1String("a")); }
47// QStringView const_char_star_does_not_compile() { return QStringView("a"); }
48// QStringView qbytearray_does_not_compile() { return QStringView(QByteArray("a")); }
49
50//
51// QChar
52//
53
54Q_STATIC_ASSERT(!CanConvert<QChar>::value);
55
56Q_STATIC_ASSERT(CanConvert<QChar[123]>::value);
57
58Q_STATIC_ASSERT(CanConvert< QString >::value);
59Q_STATIC_ASSERT(CanConvert<const QString >::value);
60Q_STATIC_ASSERT(CanConvert< QString&>::value);
61Q_STATIC_ASSERT(CanConvert<const QString&>::value);
62
63Q_STATIC_ASSERT(CanConvert< QStringRef >::value);
64Q_STATIC_ASSERT(CanConvert<const QStringRef >::value);
65Q_STATIC_ASSERT(CanConvert< QStringRef&>::value);
66Q_STATIC_ASSERT(CanConvert<const QStringRef&>::value);
67
68
69//
70// ushort
71//
72
73Q_STATIC_ASSERT(!CanConvert<ushort>::value);
74
75Q_STATIC_ASSERT(CanConvert<ushort[123]>::value);
76
77Q_STATIC_ASSERT(CanConvert< ushort*>::value);
78Q_STATIC_ASSERT(CanConvert<const ushort*>::value);
79
80
81//
82// char16_t
83//
84
85#if defined(Q_COMPILER_UNICODE_STRINGS)
86
87Q_STATIC_ASSERT(!CanConvert<char16_t>::value);
88
89Q_STATIC_ASSERT(CanConvert< char16_t*>::value);
90Q_STATIC_ASSERT(CanConvert<const char16_t*>::value);
91
92#endif
93
94#if defined(Q_STDLIB_UNICODE_STRINGS)
95
96Q_STATIC_ASSERT(CanConvert< std::u16string >::value);
97Q_STATIC_ASSERT(CanConvert<const std::u16string >::value);
98Q_STATIC_ASSERT(CanConvert< std::u16string&>::value);
99Q_STATIC_ASSERT(CanConvert<const std::u16string&>::value);
100
101#endif
102
103
104//
105// wchar_t
106//
107
108Q_CONSTEXPR bool CanConvertFromWCharT =
109#ifdef Q_OS_WIN
110 true
111#else
112 false
113#endif
114 ;
115
116Q_STATIC_ASSERT(!CanConvert<wchar_t>::value);
117
118Q_STATIC_ASSERT(CanConvert< wchar_t*>::value == CanConvertFromWCharT);
119Q_STATIC_ASSERT(CanConvert<const wchar_t*>::value == CanConvertFromWCharT);
120
121Q_STATIC_ASSERT(CanConvert< std::wstring >::value == CanConvertFromWCharT);
122Q_STATIC_ASSERT(CanConvert<const std::wstring >::value == CanConvertFromWCharT);
123Q_STATIC_ASSERT(CanConvert< std::wstring&>::value == CanConvertFromWCharT);
124Q_STATIC_ASSERT(CanConvert<const std::wstring&>::value == CanConvertFromWCharT);
125
126
127class tst_QStringView : public QObject
128{
129 Q_OBJECT
130
131private Q_SLOTS:
132 void constExpr() const;
133 void basics() const;
134 void literals() const;
135 void at() const;
136
137 void arg() const;
138
139 void fromQString() const;
140 void fromQStringRef() const;
141
142 void fromQCharStar() const
143 {
144 const QChar str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
145 fromLiteral(arg: str);
146 }
147
148 void fromUShortStar() const
149 {
150 const ushort str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
151 fromLiteral(arg: str);
152 }
153
154 void fromChar16TStar() const
155 {
156#if defined(Q_COMPILER_UNICODE_STRINGS)
157 fromLiteral(arg: u"Hello, World!");
158#else
159 QSKIP("This test requires C++11 char16_t support enabled in the compiler");
160#endif
161 }
162
163 void fromWCharTStar() const
164 {
165#ifdef Q_OS_WIN
166 fromLiteral(L"Hello, World!");
167#else
168 QSKIP("This is a Windows-only test");
169#endif
170 }
171
172 void fromQCharRange() const
173 {
174 const QChar str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
175 fromRange(first: std::begin(arr: str), last: std::end(arr: str));
176 }
177
178 void fromUShortRange() const
179 {
180 const ushort str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
181 fromRange(first: std::begin(arr: str), last: std::end(arr: str));
182 }
183
184 void fromChar16TRange() const
185 {
186#if defined(Q_COMPILER_UNICODE_STRINGS)
187 const char16_t str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
188 fromRange(first: std::begin(arr: str), last: std::end(arr: str));
189#else
190 QSKIP("This test requires C++11 char16_t support enabled in the compiler");
191#endif
192 }
193
194 void fromWCharTRange() const
195 {
196#ifdef Q_OS_WIN
197 const wchar_t str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
198 fromRange(std::begin(str), std::end(str));
199#else
200 QSKIP("This is a Windows-only test");
201#endif
202 }
203
204 // std::basic_string
205 void fromStdStringWCharT() const
206 {
207#ifdef Q_OS_WIN
208 fromStdString<wchar_t>();
209#else
210 QSKIP("This is a Windows-only test");
211#endif
212 }
213 void fromStdStringChar16T() const
214 {
215#ifdef Q_STDLIB_UNICODE_STRINGS
216 fromStdString<char16_t>();
217#else
218 QSKIP("This test requires C++11 char16_t support enabled in compiler & stdlib");
219#endif
220 }
221
222 void comparison();
223
224 void overloadResolution();
225
226private:
227 template <typename String>
228 void conversion_tests(String arg) const;
229 template <typename Char>
230 void fromLiteral(const Char *arg) const;
231 template <typename Char>
232 void fromRange(const Char *first, const Char *last) const;
233 template <typename Char, typename Container>
234 void fromContainer() const;
235 template <typename Char>
236 void fromStdString() const { fromContainer<Char, std::basic_string<Char> >(); }
237};
238
239void tst_QStringView::constExpr() const
240{
241 // compile-time checks
242#ifdef Q_COMPILER_CONSTEXPR
243 {
244 constexpr QStringView sv;
245 Q_STATIC_ASSERT(sv.size() == 0);
246 Q_STATIC_ASSERT(sv.isNull());
247 Q_STATIC_ASSERT(sv.empty());
248 Q_STATIC_ASSERT(sv.isEmpty());
249 Q_STATIC_ASSERT(sv.utf16() == nullptr);
250
251 constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
252 Q_STATIC_ASSERT(sv2.isNull());
253 Q_STATIC_ASSERT(sv2.empty());
254 }
255 {
256 constexpr QStringView sv = nullptr;
257 Q_STATIC_ASSERT(sv.size() == 0);
258 Q_STATIC_ASSERT(sv.isNull());
259 Q_STATIC_ASSERT(sv.empty());
260 Q_STATIC_ASSERT(sv.isEmpty());
261 Q_STATIC_ASSERT(sv.utf16() == nullptr);
262 }
263 {
264 constexpr QStringView sv = u"";
265 Q_STATIC_ASSERT(sv.size() == 0);
266 Q_STATIC_ASSERT(!sv.isNull());
267 Q_STATIC_ASSERT(sv.empty());
268 Q_STATIC_ASSERT(sv.isEmpty());
269 Q_STATIC_ASSERT(sv.utf16() != nullptr);
270
271 constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
272 Q_STATIC_ASSERT(!sv2.isNull());
273 Q_STATIC_ASSERT(sv2.empty());
274 }
275 {
276 constexpr QStringView sv = u"Hello";
277 Q_STATIC_ASSERT(sv.size() == 5);
278 Q_STATIC_ASSERT(!sv.empty());
279 Q_STATIC_ASSERT(!sv.isEmpty());
280 Q_STATIC_ASSERT(!sv.isNull());
281 Q_STATIC_ASSERT(*sv.utf16() == 'H');
282 Q_STATIC_ASSERT(sv[0] == QLatin1Char('H'));
283 Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H'));
284 Q_STATIC_ASSERT(sv.front() == QLatin1Char('H'));
285 Q_STATIC_ASSERT(sv.first() == QLatin1Char('H'));
286 Q_STATIC_ASSERT(sv[4] == QLatin1Char('o'));
287 Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
288 Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
289 Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
290
291 constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
292 Q_STATIC_ASSERT(!sv2.isNull());
293 Q_STATIC_ASSERT(!sv2.empty());
294 Q_STATIC_ASSERT(sv2.size() == 5);
295 }
296#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
297 {
298 Q_STATIC_ASSERT(QStringView(u"Hello").size() == 5);
299 constexpr QStringView sv = u"Hello";
300 Q_STATIC_ASSERT(sv.size() == 5);
301 Q_STATIC_ASSERT(!sv.empty());
302 Q_STATIC_ASSERT(!sv.isEmpty());
303 Q_STATIC_ASSERT(!sv.isNull());
304 Q_STATIC_ASSERT(*sv.utf16() == 'H');
305 Q_STATIC_ASSERT(sv[0] == QLatin1Char('H'));
306 Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H'));
307 Q_STATIC_ASSERT(sv.front() == QLatin1Char('H'));
308 Q_STATIC_ASSERT(sv.first() == QLatin1Char('H'));
309 Q_STATIC_ASSERT(sv[4] == QLatin1Char('o'));
310 Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
311 Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
312 Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
313
314 constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
315 Q_STATIC_ASSERT(!sv2.isNull());
316 Q_STATIC_ASSERT(!sv2.empty());
317 Q_STATIC_ASSERT(sv2.size() == 5);
318
319 constexpr char16_t *null = nullptr;
320 constexpr QStringView sv3(null);
321 Q_STATIC_ASSERT(sv3.isNull());
322 Q_STATIC_ASSERT(sv3.isEmpty());
323 Q_STATIC_ASSERT(sv3.size() == 0);
324 }
325#else // storage_type is wchar_t
326 {
327 Q_STATIC_ASSERT(QStringView(L"Hello").size() == 5);
328 constexpr QStringView sv = L"Hello";
329 Q_STATIC_ASSERT(sv.size() == 5);
330 Q_STATIC_ASSERT(!sv.empty());
331 Q_STATIC_ASSERT(!sv.isEmpty());
332 Q_STATIC_ASSERT(!sv.isNull());
333 Q_STATIC_ASSERT(*sv.utf16() == 'H');
334 Q_STATIC_ASSERT(sv[0] == QLatin1Char('H'));
335 Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H'));
336 Q_STATIC_ASSERT(sv.front() == QLatin1Char('H'));
337 Q_STATIC_ASSERT(sv.first() == QLatin1Char('H'));
338 Q_STATIC_ASSERT(sv[4] == QLatin1Char('o'));
339 Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
340 Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
341 Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
342
343 constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
344 Q_STATIC_ASSERT(!sv2.isNull());
345 Q_STATIC_ASSERT(!sv2.empty());
346 Q_STATIC_ASSERT(sv2.size() == 5);
347
348 constexpr wchar_t *null = nullptr;
349 constexpr QStringView sv3(null);
350 Q_STATIC_ASSERT(sv3.isNull());
351 Q_STATIC_ASSERT(sv3.isEmpty());
352 Q_STATIC_ASSERT(sv3.size() == 0);
353 }
354#endif
355#endif
356}
357
358void tst_QStringView::basics() const
359{
360 QStringView sv1;
361
362 // a default-constructed QStringView is null:
363 QVERIFY(sv1.isNull());
364 // which implies it's empty();
365 QVERIFY(sv1.isEmpty());
366
367 QStringView sv2;
368
369 QVERIFY(sv2 == sv1);
370 QVERIFY(!(sv2 != sv1));
371}
372
373void tst_QStringView::literals() const
374{
375#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
376 const char16_t hello[] = u"Hello";
377 const char16_t longhello[] =
378 u"Hello World. This is a much longer message, to exercise qustrlen.";
379 const char16_t withnull[] = u"a\0zzz";
380#else // storage_type is wchar_t
381 const wchar_t hello[] = L"Hello";
382 const wchar_t longhello[] =
383 L"Hello World. This is a much longer message, to exercise qustrlen.";
384 const wchar_t withnull[] = L"a\0zzz";
385#endif
386 Q_STATIC_ASSERT(sizeof(longhello) >= 16);
387
388 QCOMPARE(QStringView(hello).size(), 5);
389 QCOMPARE(QStringView(hello + 0).size(), 5); // forces decay to pointer
390 QStringView sv = hello;
391 QCOMPARE(sv.size(), 5);
392 QVERIFY(!sv.empty());
393 QVERIFY(!sv.isEmpty());
394 QVERIFY(!sv.isNull());
395 QCOMPARE(*sv.utf16(), 'H');
396 QCOMPARE(sv[0], QLatin1Char('H'));
397 QCOMPARE(sv.at(0), QLatin1Char('H'));
398 QCOMPARE(sv.front(), QLatin1Char('H'));
399 QCOMPARE(sv.first(), QLatin1Char('H'));
400 QCOMPARE(sv[4], QLatin1Char('o'));
401 QCOMPARE(sv.at(4), QLatin1Char('o'));
402 QCOMPARE(sv.back(), QLatin1Char('o'));
403 QCOMPARE(sv.last(), QLatin1Char('o'));
404
405 QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
406 QVERIFY(!sv2.isNull());
407 QVERIFY(!sv2.empty());
408 QCOMPARE(sv2.size(), 5);
409
410 QStringView sv3(longhello);
411 QCOMPARE(size_t(sv3.size()), sizeof(longhello)/sizeof(longhello[0]) - 1);
412 QCOMPARE(sv3.last(), QLatin1Char('.'));
413 sv3 = longhello;
414 QCOMPARE(size_t(sv3.size()), sizeof(longhello)/sizeof(longhello[0]) - 1);
415
416 for (int i = 0; i < sv3.size(); ++i) {
417 QStringView sv4(longhello + i);
418 QCOMPARE(size_t(sv4.size()), sizeof(longhello)/sizeof(longhello[0]) - 1 - i);
419 QCOMPARE(sv4.last(), QLatin1Char('.'));
420 sv4 = longhello + i;
421 QCOMPARE(size_t(sv4.size()), sizeof(longhello)/sizeof(longhello[0]) - 1 - i);
422 }
423
424 // these are different results
425 QCOMPARE(size_t(QStringView(withnull).size()), sizeof(withnull)/sizeof(withnull[0]) - 1);
426 QCOMPARE(QStringView(withnull + 0).size(), 1);
427}
428
429void tst_QStringView::at() const
430{
431 QString hello("Hello");
432 QStringView sv(hello);
433 QCOMPARE(sv.at(0), QChar('H')); QCOMPARE(sv[0], QChar('H'));
434 QCOMPARE(sv.at(1), QChar('e')); QCOMPARE(sv[1], QChar('e'));
435 QCOMPARE(sv.at(2), QChar('l')); QCOMPARE(sv[2], QChar('l'));
436 QCOMPARE(sv.at(3), QChar('l')); QCOMPARE(sv[3], QChar('l'));
437 QCOMPARE(sv.at(4), QChar('o')); QCOMPARE(sv[4], QChar('o'));
438}
439
440void tst_QStringView::arg() const
441{
442#define CHECK1(pattern, arg1, expected) \
443 do { \
444 auto p = QStringView(u"" pattern); \
445 QCOMPARE(p.arg(QLatin1String(arg1)), expected); \
446 QCOMPARE(p.arg(u"" arg1), expected); \
447 QCOMPARE(p.arg(QStringLiteral(arg1)), expected); \
448 QCOMPARE(p.arg(QString(QLatin1String(arg1))), expected); \
449 } while (false) \
450 /*end*/
451#define CHECK2(pattern, arg1, arg2, expected) \
452 do { \
453 auto p = QStringView(u"" pattern); \
454 QCOMPARE(p.arg(QLatin1String(arg1), QLatin1String(arg2)), expected); \
455 QCOMPARE(p.arg(u"" arg1, QLatin1String(arg2)), expected); \
456 QCOMPARE(p.arg(QLatin1String(arg1), u"" arg2), expected); \
457 QCOMPARE(p.arg(u"" arg1, u"" arg2), expected); \
458 } while (false) \
459 /*end*/
460
461 CHECK1("", "World", "");
462 CHECK1("%1", "World", "World");
463 CHECK1("!%1?", "World", "!World?");
464 CHECK1("%1%1", "World", "WorldWorld");
465 CHECK1("%1%2", "World", "World%2");
466 CHECK1("%2%1", "World", "%2World");
467
468 CHECK2("", "Hello", "World", "");
469 CHECK2("%1", "Hello", "World", "Hello");
470 CHECK2("!%1, %2?", "Hello", "World", "!Hello, World?");
471 CHECK2("%1%1", "Hello", "World", "HelloHello");
472 CHECK2("%1%2", "Hello", "World", "HelloWorld");
473 CHECK2("%2%1", "Hello", "World", "WorldHello");
474
475#undef CHECK2
476#undef CHECK1
477
478 QCOMPARE(QStringView(u" %2 %2 %1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'), " \r \r c C ");
479}
480
481void tst_QStringView::fromQString() const
482{
483 QString null;
484 QString empty = "";
485
486 QVERIFY( QStringView(null).isNull());
487 QVERIFY( QStringView(null).isEmpty());
488 QVERIFY( QStringView(empty).isEmpty());
489 QVERIFY(!QStringView(empty).isNull());
490
491 conversion_tests(string: QString("Hello World!"));
492}
493
494void tst_QStringView::fromQStringRef() const
495{
496 QStringRef null;
497 QString emptyS = "";
498 QStringRef empty(&emptyS);
499
500 QVERIFY( QStringView(null).isNull());
501 QVERIFY( QStringView(null).isEmpty());
502 QVERIFY( QStringView(empty).isEmpty());
503 QVERIFY(!QStringView(empty).isNull());
504
505 conversion_tests(string: QString("Hello World!").midRef(position: 6));
506}
507
508template <typename Char>
509void tst_QStringView::fromLiteral(const Char *arg) const
510{
511 const Char *null = nullptr;
512 const Char empty[] = { 0 };
513
514 QCOMPARE(QStringView(null).size(), qsizetype(0));
515 QCOMPARE(QStringView(null).data(), nullptr);
516 QCOMPARE(QStringView(empty).size(), qsizetype(0));
517 QCOMPARE(static_cast<const void*>(QStringView(empty).data()),
518 static_cast<const void*>(empty));
519
520 QVERIFY( QStringView(null).isNull());
521 QVERIFY( QStringView(null).isEmpty());
522 QVERIFY( QStringView(empty).isEmpty());
523 QVERIFY(!QStringView(empty).isNull());
524
525 conversion_tests(arg);
526}
527
528template <typename Char>
529void tst_QStringView::fromRange(const Char *first, const Char *last) const
530{
531 const Char *null = nullptr;
532 QCOMPARE(QStringView(null, null).size(), 0);
533 QCOMPARE(QStringView(null, null).data(), nullptr);
534 QCOMPARE(QStringView(first, first).size(), 0);
535 QCOMPARE(static_cast<const void*>(QStringView(first, first).data()),
536 static_cast<const void*>(first));
537
538 const auto sv = QStringView(first, last);
539 QCOMPARE(sv.size(), last - first);
540 QCOMPARE(static_cast<const void*>(sv.data()),
541 static_cast<const void*>(first));
542
543 // can't call conversion_tests() here, as it requires a single object
544}
545
546template <typename Char, typename Container>
547void tst_QStringView::fromContainer() const
548{
549 const QString s = "Hello World!";
550
551 Container c;
552 // unspecified whether empty containers make null QStringViews
553 QVERIFY(QStringView(c).isEmpty());
554
555 QCOMPARE(sizeof(Char), sizeof(QChar));
556
557 const auto *data = reinterpret_cast<const Char *>(s.utf16());
558 std::copy(data, data + s.size(), std::back_inserter(c));
559 conversion_tests(std::move(c));
560}
561
562namespace help {
563template <typename T>
564size_t size(const T &t) { return size_t(t.size()); }
565template <typename T>
566size_t size(const T *t)
567{
568 size_t result = 0;
569 if (t) {
570 while (*t++)
571 ++result;
572 }
573 return result;
574}
575size_t size(const QChar *t)
576{
577 size_t result = 0;
578 if (t) {
579 while (!t++->isNull())
580 ++result;
581 }
582 return result;
583}
584
585template <typename T>
586typename T::const_iterator cbegin(const T &t) { return t.cbegin(); }
587template <typename T>
588const T * cbegin(const T *t) { return t; }
589
590template <typename T>
591typename T::const_iterator cend(const T &t) { return t.cend(); }
592template <typename T>
593const T * cend(const T *t) { return t + size(t); }
594
595template <typename T>
596typename T::const_reverse_iterator crbegin(const T &t) { return t.crbegin(); }
597template <typename T>
598std::reverse_iterator<const T*> crbegin(const T *t) { return std::reverse_iterator<const T*>(cend(t)); }
599
600template <typename T>
601typename T::const_reverse_iterator crend(const T &t) { return t.crend(); }
602template <typename T>
603std::reverse_iterator<const T*> crend(const T *t) { return std::reverse_iterator<const T*>(cbegin(t)); }
604
605} // namespace help
606
607template <typename String>
608void tst_QStringView::conversion_tests(String string) const
609{
610 // copy-construct:
611 {
612 QStringView sv = string;
613
614 QCOMPARE(help::size(sv), help::size(string));
615
616 // check iterators:
617
618 QVERIFY(std::equal(help::cbegin(string), help::cend(string),
619 QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.cbegin(), sv.size())));
620 QVERIFY(std::equal(help::cbegin(string), help::cend(string),
621 QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.begin(), sv.size())));
622 QVERIFY(std::equal(help::crbegin(string), help::crend(string),
623 sv.crbegin()));
624 QVERIFY(std::equal(help::crbegin(string), help::crend(string),
625 sv.rbegin()));
626
627 QCOMPARE(sv, string);
628 }
629
630 QStringView sv;
631
632 // copy-assign:
633 {
634 sv = string;
635
636 QCOMPARE(help::size(sv), help::size(string));
637
638 // check relational operators:
639
640 QCOMPARE(sv, string);
641 QCOMPARE(string, sv);
642
643 QVERIFY(!(sv != string));
644 QVERIFY(!(string != sv));
645
646 QVERIFY(!(sv < string));
647 QVERIFY(sv <= string);
648 QVERIFY(!(sv > string));
649 QVERIFY(sv >= string);
650
651 QVERIFY(!(string < sv));
652 QVERIFY(string <= sv);
653 QVERIFY(!(string > sv));
654 QVERIFY(string >= sv);
655 }
656
657 // copy-construct from rvalue (QStringView never assumes ownership):
658 {
659 QStringView sv2 = std::move(string);
660 QCOMPARE(sv2, sv);
661 QCOMPARE(sv2, string);
662 }
663
664 // copy-assign from rvalue (QStringView never assumes ownership):
665 {
666 QStringView sv2;
667 sv2 = std::move(string);
668 QCOMPARE(sv2, sv);
669 QCOMPARE(sv2, string);
670 }
671}
672
673void tst_QStringView::comparison()
674{
675 const QStringView aa = u"aa";
676 const QStringView upperAa = u"AA";
677 const QStringView bb = u"bb";
678
679 QVERIFY(aa == aa);
680 QVERIFY(aa != bb);
681 QVERIFY(aa < bb);
682 QVERIFY(bb > aa);
683
684 QCOMPARE(aa.compare(aa), 0);
685 QVERIFY(aa.compare(upperAa) != 0);
686 QCOMPARE(aa.compare(upperAa, Qt::CaseInsensitive), 0);
687 QVERIFY(aa.compare(bb) < 0);
688 QVERIFY(bb.compare(aa) > 0);
689}
690
691namespace QStringViewOverloadResolution {
692static void test(QString) = delete;
693static void test(QStringView) {}
694}
695
696// Compile-time only test: overload resolution prefers QStringView over QString
697void tst_QStringView::overloadResolution()
698{
699 {
700 QChar qcharArray[42] = {};
701 QStringViewOverloadResolution::test(qcharArray);
702 QChar *qcharPointer = qcharArray;
703 QStringViewOverloadResolution::test(qcharPointer);
704 }
705
706 {
707 ushort ushortArray[42] = {};
708 QStringViewOverloadResolution::test(ushortArray);
709 ushort *ushortPointer = ushortArray;
710 QStringViewOverloadResolution::test(ushortPointer);
711 }
712
713 {
714 QStringRef stringRef;
715 QStringViewOverloadResolution::test(stringRef);
716 QStringViewOverloadResolution::test(qAsConst(t&: stringRef));
717 QStringViewOverloadResolution::test(std::move(stringRef));
718 }
719
720#if defined(Q_OS_WIN)
721 {
722 wchar_t wchartArray[42] = {};
723 QStringViewOverloadResolution::test(wchartArray);
724 QStringViewOverloadResolution::test(L"test");
725 }
726#endif
727
728#if defined(Q_COMPILER_UNICODE_STRINGS)
729 {
730 char16_t char16Array[] = u"test";
731 QStringViewOverloadResolution::test(char16Array);
732 char16_t *char16Pointer = char16Array;
733 QStringViewOverloadResolution::test(char16Pointer);
734 }
735#endif
736
737#if defined(Q_STDLIB_UNICODE_STRINGS)
738 {
739 std::u16string string;
740 QStringViewOverloadResolution::test(string);
741 QStringViewOverloadResolution::test(qAsConst(t&: string));
742 QStringViewOverloadResolution::test(std::move(string));
743 }
744#endif
745}
746
747QTEST_APPLESS_MAIN(tst_QStringView)
748#include "tst_qstringview.moc"
749

source code of qtbase/tests/auto/corelib/text/qstringview/tst_qstringview.cpp