1// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qanystringview.h"
5#include "qdebug.h"
6#include "qttypetraits.h"
7
8QT_BEGIN_NAMESPACE
9
10/*!
11 \class QAnyStringView
12 \inmodule QtCore
13 \since 6.0
14 \brief The QAnyStringView class provides a unified view on Latin-1, UTF-8,
15 or UTF-16 strings with a read-only subset of the QString API.
16 \reentrant
17 \ingroup tools
18 \ingroup string-processing
19
20 \compares strong
21 \compareswith strong char16_t QChar {const char16_t *} {const char *} \
22 QByteArray QByteArrayView QString QStringView QUtf8StringView \
23 QLatin1StringView
24 \endcompareswith
25
26 A QAnyStringView references a contiguous portion of a string it does
27 not own. It acts as an interface type to all kinds of strings,
28 without the need to construct a QString first.
29
30 Unlike QStringView and QUtf8StringView, QAnyStringView can hold
31 strings of any of the following encodings: UTF-8, UTF-16, and
32 Latin-1. The latter is supported because Latin-1, unlike UTF-8,
33 can be efficiently compared to UTF-16 data: a length mismatch
34 already means the strings cannot be equal. This is not true for
35 UTF-8/UTF-16 comparisons, because UTF-8 is a variable-length
36 encoding.
37
38 The string may be represented as an array (or an array-compatible
39 data-structure such as QString, std::basic_string, etc.) of \c
40 char, \c char8_t, QChar, \c ushort, \c char16_t or (on platforms,
41 such as Windows, where it is a 16-bit type) \c wchar_t.
42
43 QAnyStringView is designed as an interface type; its main use-case
44 is as a function parameter type. When QAnyStringViews are used as
45 automatic variables or data members, care must be taken to ensure
46 that the referenced string data (for example, owned by a QString)
47 outlives the QAnyStringView on all code paths, lest the string
48 view ends up referencing deleted data.
49
50 When used as an interface type, QAnyStringView allows a single
51 function to accept a wide variety of string data sources. One
52 function accepting QAnyStringView thus replaces five function
53 overloads (taking QString, \c{(const QChar*, qsizetype)},
54 QUtf8StringView, QLatin1StringView (but see above), and QChar), while
55 at the same time enabling even more string data sources to be
56 passed to the function, such as \c{u8"Hello World"}, a \c char8_t
57 string literal.
58
59 Like elsewhere in Qt, QAnyStringView assumes \c char data is encoded
60 in UTF-8, unless it is presented as a QLatin1StringView.
61
62 Since Qt 6.4, however, UTF-8 string literals that are pure US-ASCII are
63 automatically stored as Latin-1. This is a compile-time check with no
64 runtime overhead. The feature requires compiling in C++20, or with a recent
65 GCC.
66
67 QAnyStringViews should be passed by value, not by reference-to-const:
68 \snippet code/src_corelib_text_qanystringview.cpp 0
69
70 QAnyStringView can also be used as the return value of a function,
71 but this is not recommended. QUtf8StringView or QStringView are
72 better suited as function return values. If you call a function
73 returning QAnyStringView, take extra care to not keep the
74 QAnyStringView around longer than the function promises to keep
75 the referenced string data alive. If in doubt, obtain a strong
76 reference to the data by calling toString() to convert the
77 QAnyStringView into a QString.
78
79 QAnyStringView is a \e{Literal Type}.
80
81 \section2 Compatible Character Types
82
83 QAnyStringView accepts strings over a variety of character types:
84
85 \list
86 \li \c char (both signed and unsigned)
87 \li \c char8_t (C++20 only)
88 \li \c char16_t
89 \li \c wchar_t (where it's a 16-bit type, e.g. Windows)
90 \li \c ushort
91 \li \c QChar
92 \endlist
93
94 The 8-bit character types are interpreted as UTF-8 data (except when
95 presented as a QLatin1StringView) while the 16-bit character types are
96 interpreted as UTF-16 data in host byte order (the same as QString).
97
98 \section2 Sizes and Sub-Strings
99
100 All sizes and positions in QAnyStringView functions are in the
101 encoding's code units (that is, UTF-16 surrogate pairs count as
102 two for the purposes of these functions, the same as in QString,
103 and UTF-8 multibyte sequences count as two, three or four,
104 depending on their length).
105
106 \sa QUtf8StringView, QStringView
107*/
108
109/*!
110 \typedef QAnyStringView::difference_type
111
112 Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
113*/
114
115/*!
116 \typedef QAnyStringView::size_type
117
118 Alias for qsizetype. Provided for compatibility with the STL.
119*/
120
121/*!
122 \fn QAnyStringView::QAnyStringView()
123
124 Constructs a null string view.
125
126 \sa isNull()
127*/
128
129/*!
130 \fn QAnyStringView::QAnyStringView(std::nullptr_t)
131
132 Constructs a null string view.
133
134 \sa isNull()
135*/
136
137/*!
138 \fn template <typename Char, QAnyStringView::if_compatible_char<Char> = true> QAnyStringView::QAnyStringView(const Char *str, qsizetype len)
139
140 Constructs a string view on \a str with length \a len.
141
142 The range \c{[str,len)} must remain valid for the lifetime of this string view object.
143
144 Passing \nullptr as \a str is safe if \a len is 0, too, and results in a null string view.
145
146 The behavior is undefined if \a len is negative or, when positive, if \a str is \nullptr.
147
148 This constructor only participates in overload resolution if \c Char is a compatible
149 character type.
150
151 \sa isNull(), {Compatible Character Types}
152*/
153
154/*!
155 \fn template <typename Char, QAnyStringView::if_compatible_char<Char> = true> QAnyStringView::QAnyStringView(const Char *first, const Char *last)
156
157 Constructs a string view on \a first with length (\a last - \a first).
158
159 The range \c{[first,last)} must remain valid for the lifetime of
160 this string view object.
161
162 Passing \nullptr as \a first is safe if \a last is \nullptr, too,
163 and results in a null string view.
164
165 The behavior is undefined if \a last precedes \a first, or \a first
166 is \nullptr and \a last is not.
167
168 This constructor only participates in overload resolution if \c Char
169 is a compatible character type.
170
171 \sa isNull(), {Compatible Character Types}
172*/
173
174/*!
175 \fn template <typename Char> QAnyStringView::QAnyStringView(const Char *str)
176
177 Constructs a string view on \a str. The length is determined
178 by scanning for the first \c{Char(0)}.
179
180 \a str must remain valid for the lifetime of this string view object.
181
182 Passing \nullptr as \a str is safe and results in a null string view.
183
184 This constructor only participates in overload resolution if \a
185 str is not an array and if \c Char is a compatible character
186 type.
187
188 \sa isNull(), {Compatible Character Types}
189*/
190
191/*!
192 \fn template <typename Char, size_t N> QAnyStringView::QAnyStringView(const Char (&string)[N])
193
194 Constructs a string view on the character string literal \a string.
195 The view covers the array until the first \c{Char(0)} is encountered,
196 or \c N, whichever comes first.
197 If you need the full array, use fromArray() instead.
198
199 \a string must remain valid for the lifetime of this string view
200 object.
201
202 This constructor only participates in overload resolution if \a
203 string is an actual array and \c Char is a compatible character
204 type.
205
206 \sa {Compatible Character Types}
207*/
208
209/*!
210 \fn QAnyStringView::QAnyStringView(const QString &str)
211
212 Constructs a string view on \a str.
213
214 \c{str.data()} must remain valid for the lifetime of this string view object.
215
216 The string view will be null if and only if \c{str.isNull()}.
217*/
218
219/*!
220 \fn QAnyStringView::QAnyStringView(const QByteArray &str)
221
222 Constructs a string view on \a str. The data in \a str is interpreted as UTF-8.
223
224 \c{str.data()} must remain valid for the lifetime of this string view object.
225
226 The string view will be null if and only if \c{str.isNull()}.
227*/
228
229/*!
230 \fn template <typename Container, QAnyStringView::if_compatible_container<Container>> QAnyStringView::QAnyStringView(const Container &str)
231
232 Constructs a string view on \a str. The length is taken from \c{std::size(str)}.
233
234 \c{std::data(str)} must remain valid for the lifetime of this string view object.
235
236 This constructor only participates in overload resolution if \c Container is a
237 container with a compatible character type as \c{value_type}.
238
239 The string view will be empty if and only if \c{std::size(str) == 0}. It is unspecified
240 whether this constructor can result in a null string view (\c{std::data(str)} would
241 have to return \nullptr for this).
242
243 \sa isNull(), isEmpty()
244*/
245
246/*!
247 \fn template <typename Char, size_t Size> static QAnyStringView fromArray(const Char (&string)[Size]) noexcept
248
249 Constructs a string view on the full character string literal \a string,
250 including any trailing \c{Char(0)}. If you don't want the
251 null-terminator included in the view then you can use the constructor
252 overload taking a pointer and a size:
253
254 \snippet code/src_corelib_text_qanystringview.cpp 2
255
256 Alternatively you can use the constructor overload taking an
257 array literal which will create a view up to, but not including,
258 the first null-terminator in the data.
259
260 \a string must remain valid for the lifetime of this string view
261 object.
262
263 This function will work with any array literal if \c Char is a
264 compatible character type.
265*/
266
267/*!
268 \fn QString QAnyStringView::toString() const
269
270 Returns a deep copy of this string view's data as a QString.
271
272 The return value will be a null QString if and only if this string view is null.
273*/
274
275/*!
276 \fn const void *QAnyStringView::data() const
277
278 Returns a const pointer to the first character in the string view.
279
280 \note The character array represented by the return value is \e not null-terminated.
281
282 \sa size_bytes()
283*/
284
285/*!
286 \fn bool QAnyStringView::empty() const
287
288 Returns whether this string view is empty - that is, whether \c{size() == 0}.
289
290 This function is provided for STL compatibility.
291
292 \sa isEmpty(), isNull(), size()
293*/
294
295/*!
296 \fn bool QAnyStringView::isEmpty() const
297
298 Returns whether this string view is empty - that is, whether \c{size() == 0}.
299
300 This function is provided for compatibility with other Qt containers.
301
302 \sa empty(), isNull(), size()
303*/
304
305/*!
306 \fn bool QAnyStringView::isNull() const
307
308 Returns whether this string view is null - that is, whether \c{data() == nullptr}.
309
310 This functions is provided for compatibility with other Qt containers.
311
312 \sa empty(), isEmpty(), size()
313*/
314
315/*!
316 \fn qsizetype QAnyStringView::size() const
317
318 Returns the size of this string view, in the encoding's code points.
319
320 \sa empty(), isEmpty(), isNull(), size_bytes(), {Sizes and Sub-Strings}
321*/
322
323/*!
324 \fn QAnyStringView::size_bytes() const
325
326 Returns the size of this string view, but in bytes, not code-points.
327
328 You can use this function together with data() for hashing or serialization.
329
330 This function is provided for STL compatibility.
331
332 \sa size(), data()
333*/
334
335/*!
336 \fn QAnyStringView::length() const
337
338 Same as size().
339
340 This function is provided for compatibility with other Qt containers.
341
342 \sa size()
343*/
344
345/*!
346 \fn QChar QAnyStringView::front() const
347
348 Returns the first character in the string view.
349
350 This function is provided for STL compatibility.
351
352 \warning Calling this function on an empty string view constitutes
353 undefined behavior.
354
355 \sa back(), {Sizes and Sub-Strings}
356*/
357
358/*!
359 \fn QChar QAnyStringView::back() const
360
361 Returns the last character in the string view.
362
363 This function is provided for STL compatibility.
364
365 \warning Calling this function on an empty string view constitutes
366 undefined behavior.
367
368 \sa front(), {Sizes and Sub-Strings}
369*/
370
371/*!
372 \fn QAnyStringView::mid(qsizetype pos, qsizetype n) const
373 \since 6.5
374
375 Returns the substring of length \a n starting at position
376 \a pos in this object.
377
378 \deprecated Use sliced() instead in new code.
379
380 Returns an empty string view if \a n exceeds the
381 length of the string view. If there are less than \a n code points
382 available in the string view starting at \a pos, or if
383 \a n is negative (default), the function returns all code points that
384 are available from \a pos.
385
386 \sa first(), last(), sliced(), chopped(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
387*/
388
389/*!
390 \fn QAnyStringView::left(qsizetype n) const
391 \since 6.5
392
393 \deprecated Use first() instead in new code.
394
395 Returns the substring of length \a n starting at position
396 0 in this object.
397
398 The entire string view is returned if \a n is greater than or equal
399 to size(), or less than zero.
400
401 \sa first(), last(), sliced(), chopped(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
402*/
403
404/*!
405 \fn QAnyStringView::right(qsizetype n) const
406 \since 6.5
407
408 \deprecated Use last() instead in new code.
409
410 Returns the substring of length \a n starting at position
411 size() - \a n in this object.
412
413 The entire string view is returned if \a n is greater than or equal
414 to size(), or less than zero.
415
416 \sa first(), last(), sliced(), chopped(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
417*/
418
419/*!
420 \fn QAnyStringView::first(qsizetype n) const
421 \since 6.5
422
423 Returns a string view that contains the first \a n code points
424 of this string view.
425
426 \note The behavior is undefined when \a n < 0 or \a n > size().
427
428 \sa last(), sliced(), chopped(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
429*/
430
431/*!
432 \fn QAnyStringView::last(qsizetype n) const
433 \since 6.5
434
435 Returns a string view that contains the last \a n code points of this string view.
436
437 \note The behavior is undefined when \a n < 0 or \a n > size().
438
439 \sa first(), sliced(), chopped(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
440*/
441
442/*!
443 \fn QAnyStringView::sliced(qsizetype pos, qsizetype n) const
444 \since 6.5
445
446 Returns a string view containing \a n code points of this string view,
447 starting at position \a pos.
448
449//! [UB-sliced-index-length]
450 \note The behavior is undefined when \a pos < 0, \a n < 0,
451 or \a pos + \a n > size().
452//! [UB-sliced-index-length]
453
454 \sa first(), last(), chopped(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
455*/
456
457/*!
458 \fn QAnyStringView::sliced(qsizetype pos) const
459 \since 6.5
460
461 Returns a string view starting at position \a pos in this object,
462 and extending to its end.
463
464//! [UB-sliced-index-only]
465 \note The behavior is undefined when \a pos < 0 or \a pos > size().
466//! [UB-sliced-index-only]
467
468 \sa first(), last(), chopped(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
469*/
470
471/*!
472 \fn QAnyStringView &QAnyStringView::slice(qsizetype pos, qsizetype n)
473 \since 6.8
474
475 Modifies this string view to start at position \a pos, extending for
476 \a n code points.
477
478 \include qanystringview.cpp UB-sliced-index-length
479
480 \sa sliced(), first(), last(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
481*/
482
483/*!
484 \fn QAnyStringView &QAnyStringView::slice(qsizetype pos)
485 \since 6.8
486 \overload
487
488 Modifies this string view to start at position \a pos, extending to
489 its end.
490
491 \include qanystringview.cpp UB-sliced-index-only
492
493 \sa sliced(), first(), last(), chopped(), chop(), truncate(), {Sizes and Sub-Strings}
494*/
495
496/*!
497 \fn QAnyStringView::chopped(qsizetype n) const
498 \since 6.5
499
500 Returns the substring of length size() - \a n starting at the
501 beginning of this object.
502
503 Same as \c{first(size() - n)}.
504
505 \note The behavior is undefined when \a n < 0 or \a n > size().
506
507 \sa sliced(), first(), last(), chop(), truncate(), slice(), {Sizes and Sub-Strings}
508*/
509
510/*!
511 \fn QAnyStringView::truncate(qsizetype n)
512 \since 6.5
513
514 Truncates this string view to \a n code points.
515
516 Same as \c{*this = first(n)}.
517
518 \note The behavior is undefined when \a n < 0 or \a n > size().
519
520 \sa sliced(), first(), last(), chopped(), chop(), {Sizes and Sub-Strings}
521*/
522
523/*!
524 \fn QAnyStringView::chop(qsizetype n)
525 \since 6.5
526
527 Truncates this string view by \a n code points.
528
529 Same as \c{*this = first(size() - n)}.
530
531 \note The behavior is undefined when \a n < 0 or \a n > size().
532
533 \sa sliced(), first(), last(), chopped(), truncate(), slice(), {Sizes and Sub-Strings}
534*/
535
536/*! \fn template <typename Visitor> decltype(auto) QAnyStringView::visit(Visitor &&v) const
537
538 Calls \a v with either a QUtf8StringView, QLatin1String, or QStringView, depending
539 on the encoding of the string data this string-view references.
540
541 This is how most functions taking QAnyStringView fork off into per-encoding
542 functions:
543
544 \code
545 void processImpl(QLatin1String s) { ~~~ }
546 void processImpl(QUtf8StringView s) { ~~~ }
547 void processImpl(QStringView s) { ~~~ }
548
549 void process(QAnyStringView s)
550 {
551 s.visit([](auto s) { processImpl(s); });
552 }
553 \endcode
554
555 Here, we're reusing the same name, \c s, for both the QAnyStringView
556 object, as well as the lambda's parameter. This is idiomatic code and helps
557 track the identity of the objects through visit() calls, for example in more
558 complex situations such as
559
560 \code
561 bool equal(QAnyStringView lhs, QAnyStringView rhs)
562 {
563 // assuming operator==(QAnyStringView, QAnyStringView) didn't, yet, exist:
564 return lhs.visit([rhs](auto lhs) {
565 rhs.visit([lhs](auto rhs) {
566 return lhs == rhs;
567 });
568 });
569 }
570 \endcode
571
572 visit() requires that all lambda instantiations have the same return type.
573 If they differ, you get a compile error, even if there is a common type. To
574 fix, you can use explicit return types on the lambda, or cast in the return
575 statements:
576
577 \code
578 // wrong:
579 QAnyStringView firstHalf(QAnyStringView input)
580 {
581 return input.visit([](auto input) { // ERROR: lambdas return different types
582 return input.sliced(0, input.size() / 2);
583 });
584 }
585 // correct:
586 QAnyStringView firstHalf(QAnyStringView input)
587 {
588 return input.visit([](auto input) -> QAnyStringView { // OK, explicit return type
589 return input.sliced(0, input.size() / 2);
590 });
591 }
592 // also correct:
593 QAnyStringView firstHalf(QAnyStringView input)
594 {
595 return input.visit([](auto input) {
596 return QAnyStringView(input.sliced(0, input.size() / 2)); // OK, cast to common type
597 });
598 }
599 \endcode
600*/
601
602/*!
603 \fn QAnyStringView::compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs)
604
605 Compares the string view \a lhs with the string view \a rhs and returns a
606 negative integer if \a lhs is less than \a rhs, a positive integer if it is
607 greater than \a rhs, and zero if they are equal.
608
609 If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
610 otherwise the comparison is case-insensitive.
611
612 \sa operator==(), operator<(), operator>()
613*/
614
615/*!
616 \fn bool QAnyStringView::operator==(const QAnyStringView &lhs, const QAnyStringView & rhs)
617 \fn bool QAnyStringView::operator!=(const QAnyStringView & lhs, const QAnyStringView & rhs)
618 \fn bool QAnyStringView::operator<=(const QAnyStringView & lhs, const QAnyStringView & rhs)
619 \fn bool QAnyStringView::operator>=(const QAnyStringView & lhs, const QAnyStringView & rhs)
620 \fn bool QAnyStringView::operator<(const QAnyStringView & lhs, const QAnyStringView & rhs)
621 \fn bool QAnyStringView::operator>(const QAnyStringView & lhs, const QAnyStringView & rhs)
622
623 Operators that compare \a lhs to \a rhs.
624
625 \sa compare()
626*/
627
628/*!
629 \fn template <typename QStringLike> qToAnyStringViewIgnoringNull(const QStringLike &s);
630 \since 6.0
631 \internal
632
633 Convert \a s to a QAnyStringView ignoring \c{s.isNull()}.
634
635 Returns a string view that references \a{s}'s data, but is never null.
636
637 This is a faster way to convert a QString or QByteArray to a QAnyStringView,
638 if null QStrings or QByteArrays can legitimately be treated as empty ones.
639
640 \sa QString::isNull(), QAnyStringView
641*/
642
643/*!
644 \fn QAnyStringView::max_size() const
645 \since 6.8
646
647 This function is provided for STL compatibility.
648
649 It returns the maximum number of elements that the string view can
650 theoretically represent. In practice, the number can be much smaller,
651 limited by the amount of memory available to the system.
652
653 \note The returned value is calculated based on the currently used character
654 type, so calling this function on two different views may return different
655 results.
656*/
657
658/*!
659 \fn QAnyStringView::operator<<(QDebug d, QAnyStringView s)
660 \since 6.7
661 \relates QDebug
662
663 Outputs \a s to debug stream \a d.
664
665 If \c{d.quotedString()} is \c true, indicates which encoding the string is
666 in. If you just want the string data, use visit() like this:
667
668 \code
669 s.visit([&d) (auto s) { d << s; });
670 \endcode
671
672 \sa QAnyStringView::visit()
673*/
674QDebug operator<<(QDebug d, QAnyStringView s)
675{
676 struct S { const char *prefix, *suffix; };
677 const auto affixes = s.visit(v: [](auto s) {
678 using View = decltype(s);
679 if constexpr (std::is_same_v<View, QLatin1StringView>) {
680 return S{.prefix: "", .suffix: "_L1"};
681 } else if constexpr (std::is_same_v<View, QUtf8StringView>) {
682 return S{.prefix: "u8", .suffix: ""};
683 } else if constexpr (std::is_same_v<View, QStringView>) {
684 return S{.prefix: "u", .suffix: ""};
685 } else {
686 static_assert(QtPrivate::type_dependent_false<View>());
687 }
688 });
689 const QDebugStateSaver saver(d);
690 d.nospace();
691 if (d.quoteStrings())
692 d << affixes.prefix;
693 s.visit(v: [&d](auto s) { d << s; });
694 if (d.quoteStrings())
695 d << affixes.suffix;
696 return d;
697}
698
699
700QT_END_NAMESPACE
701

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/corelib/text/qanystringview.cpp