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 | |
8 | QT_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 | */ |
674 | QDebug 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 | |
700 | QT_END_NAMESPACE |
701 | |