Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qstring.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2019 Intel Corporation.
3// Copyright (C) 2019 Mail.ru Group.
4// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
5// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
6// Qt-Security score:critical reason:data-parser
7
8#ifndef QSTRING_H
9#define QSTRING_H
10
11#if defined(QT_NO_CAST_FROM_ASCII) && defined(QT_RESTRICTED_CAST_FROM_ASCII)
12#error QT_NO_CAST_FROM_ASCII and QT_RESTRICTED_CAST_FROM_ASCII must not be defined at the same time
13#endif
14
15#include <QtCore/qchar.h>
16#include <QtCore/qcompare.h>
17#include <QtCore/qbytearray.h>
18#include <QtCore/qbytearrayview.h>
19#include <QtCore/qarraydata.h>
20#include <QtCore/qarraydatapointer.h>
21#include <QtCore/qlatin1stringview.h>
22#include <QtCore/qnamespace.h>
23#include <QtCore/qstringalgorithms.h>
24#include <QtCore/qanystringview.h>
25#include <QtCore/qstringtokenizer.h>
26
27#include <string>
28#include <iterator>
29#include <QtCore/q20memory.h>
30#include <string_view>
31#include <QtCore/q23type_traits.h>
32
33#include <stdarg.h>
34
35#ifdef truncate
36#error qstring.h must be included before any header file that defines truncate
37#endif
38
39#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
40Q_FORWARD_DECLARE_CF_TYPE(CFString);
41Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
42#endif
43
44class tst_QString;
45
46QT_BEGIN_NAMESPACE
47
48class qfloat16;
49class QRegularExpression;
50class QRegularExpressionMatch;
51class QString;
52
53namespace QtPrivate {
54template <bool...B> class BoolList;
55
56template <typename Char>
58 std::is_same<Char, char32_t>;
59template <typename Char>
62
63// hack to work around ushort/uchar etc being treated as both characters and
64// integers, depending on which Qt API you look at:
65template <typename T> struct treat_as_integral_arg : std::false_type {};
66template <> struct treat_as_integral_arg<unsigned short> : std::true_type {};
67template <> struct treat_as_integral_arg< signed short> : std::true_type {};
68template <> struct treat_as_integral_arg<unsigned char> : std::true_type {};
69template <> struct treat_as_integral_arg< signed char> : std::true_type {};
70}
71
72// Qt 4.x compatibility
73
74//
75// QLatin1StringView inline implementations
76//
77constexpr bool QtPrivate::isLatin1(QLatin1StringView) noexcept
78{ return true; }
79
80//
81// QStringView members that require QLatin1StringView:
82//
83int QStringView::compare(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
84{
85#if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
86 if (__builtin_constant_p(s.m_size) && s.size() == 1)
87 return compare(s.front(), cs);
88#endif
89 return QtPrivate::compareStrings(*this, s, cs);
90}
91bool QStringView::startsWith(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
92{
93#if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
94 if (__builtin_constant_p(s.m_size) && s.size() == 1)
95 return startsWith(s.front(), cs);
96#endif
97 return QtPrivate::startsWith(*this, s, cs);
98}
99bool QStringView::endsWith(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
100{
101#if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
102 if (__builtin_constant_p(s.m_size) && s.size() == 1)
103 return endsWith(s.front(), cs);
104#endif
105 return QtPrivate::endsWith(*this, s, cs);
106}
107qsizetype QStringView::indexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
108{
109#if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
110 if (__builtin_constant_p(s.m_size) && s.size() == 1)
111 return indexOf(s.front(), from, cs);
112#endif
113 return QtPrivate::findString(*this, from, s, cs);
114}
115bool QStringView::contains(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
116{ return indexOf(s, 0, cs) != qsizetype(-1); }
117qsizetype QStringView::lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs) const noexcept
118{ return lastIndexOf(s, size(), cs); }
119qsizetype QStringView::lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
120{
121#if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
122 if (__builtin_constant_p(s.m_size) && s.size() == 1)
123 return lastIndexOf(s.front(), from, cs);
124#endif
125 return QtPrivate::lastIndexOf(*this, from, s, cs);
126}
127qsizetype QStringView::count(QLatin1StringView s, Qt::CaseSensitivity cs) const
128{
129#if defined(Q_CC_GNU) || __has_builtin(__builtin_constant_p)
130 if (__builtin_constant_p(s.m_size) && s.size() == 1)
131 return count(s.front(), cs);
132#endif
133 return QtPrivate::count(*this, s, cs);
134}
135
136//
137// QAnyStringView members that require QLatin1StringView
138//
139
140constexpr QAnyStringView::QAnyStringView(QLatin1StringView str) noexcept
141 : m_data{str.data()}, m_size{size_t(str.size() << SizeShift) | Tag::Latin1} {}
142
143constexpr QLatin1StringView QAnyStringView::asLatin1StringView() const
144{
145 Q_ASSERT(isLatin1());
146 return {m_data_utf8, size()};
147}
148
149
150template <typename Visitor>
151constexpr decltype(auto) QAnyStringView::visit(Visitor &&v) const
152{
153 if (isUtf16())
154 return std::forward<Visitor>(v)(asStringView());
155 else if (isLatin1())
156 return std::forward<Visitor>(v)(asLatin1StringView());
157 else
158 return std::forward<Visitor>(v)(asUtf8StringView());
159}
160
161//
162// QAnyStringView members that require QAnyStringView::visit()
163//
164
165constexpr QChar QAnyStringView::front() const
166{
167 return visit([] (auto that) { return QAnyStringView::toQChar(that.front()); });
168}
169constexpr QChar QAnyStringView::back() const
170{
171 return visit([] (auto that) { return QAnyStringView::toQChar(that.back()); });
172}
173
174using QStringPrivate = QArrayDataPointer<char16_t>;
175
176class Q_CORE_EXPORT QString
177{
178 typedef QTypedArrayData<char16_t> Data;
179
180 friend class ::tst_QString;
181
182 template <typename Iterator>
183 static constexpr bool is_contiguous_iterator_v =
184 // Can't use contiguous_iterator_tag here, as STL impls can't agree on feature macro.
185 // To avoid differences in C++20 and C++17 builds, treat only pointers as contiguous
186 // for now:
187 // std::contiguous_iterator<Iterator>;
188 std::is_pointer_v<Iterator>;
189
190 template <typename Char>
191 using is_compatible_char_helper = std::disjunction<
192 QtPrivate::IsCompatibleCharType<Char>,
193 QtPrivate::IsCompatibleChar32Type<Char>,
194 QtPrivate::IsCompatibleChar8Type<Char>,
195 std::is_same<Char, QLatin1Char> // special case
196 >;
197
198 template <typename T>
199 using is_string_like = std::conjunction<
200 std::negation<QtPrivate::treat_as_integral_arg<std::remove_cv_t<T>>>, // used to be integral, so keep
201 std::is_convertible<T, QAnyStringView>
202 >;
203
204 template <typename T>
205 using if_string_like = std::enable_if_t<is_string_like<T>::value, bool>;
206
207 template <typename T>
208 using is_floating_point_like = std::disjunction<
209 #if QFLOAT16_IS_NATIVE
210 std::is_same<q20::remove_cvref_t<T>, QtPrivate::NativeFloat16Type>,
211 #endif
212 std::is_same<q20::remove_cvref_t<T>, qfloat16>,
213 std::is_floating_point<T>
214 >;
215
216 template <typename T>
217 using if_floating_point = std::enable_if_t<is_floating_point_like<T>::value, bool>;
218
219 template <typename T>
220 using if_integral_non_char = std::enable_if_t<std::conjunction_v<
221 std::disjunction<
222 std::is_integral<T>,
223 std::conjunction<
224 std::is_enum<T>, // (unscoped) enums yes,
225 std::negation<q23::is_scoped_enum<T>> // but not scoped ones
226 >
227 >,
228 std::negation<is_floating_point_like<T>>, // has its own overload
229 std::negation<is_string_like<T>> // ditto
230 >, bool>;
231
232 template <typename Iterator>
233 static constexpr bool is_compatible_iterator_v = std::conjunction_v<
234 std::is_convertible<
235 typename std::iterator_traits<Iterator>::iterator_category,
236 std::input_iterator_tag
237 >,
238 is_compatible_char_helper<typename std::iterator_traits<Iterator>::value_type>
239 >;
240
241 template <typename Iterator>
242 using if_compatible_iterator = std::enable_if_t<is_compatible_iterator_v<Iterator>, bool>;
243
244public:
245 typedef QStringPrivate DataPointer;
246
247 constexpr QString() noexcept;
248 explicit QString(const QChar *unicode, qsizetype size = -1);
249 QString(QChar c);
250 QString(qsizetype size, QChar c);
251 inline QString(QLatin1StringView latin1);
252 explicit QString(QStringView sv) : QString(sv.data(), sv.size()) {}
253#if defined(__cpp_char8_t) || defined(Q_QDOC)
254 Q_WEAK_OVERLOAD
255 inline QString(const char8_t *str)
256 : QString(fromUtf8(str))
257 {}
258#endif
259 inline QString(const QString &) noexcept;
260 inline ~QString();
261 QString &operator=(QChar c);
262 QString &operator=(const QString &) noexcept;
263 QString &operator=(QLatin1StringView latin1);
264 inline QString(QString &&other) noexcept
265 = default;
266 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QString)
267 void swap(QString &other) noexcept { d.swap(other.d); }
268
269 static constexpr qsizetype maxSize() noexcept
270 {
271 // -1 to deal with the NUL terminator
272 return Data::maxSize() - 1;
273 }
274 constexpr qsizetype size() const noexcept
275 {
276 constexpr size_t MaxSize = maxSize();
277 Q_PRESUME(size_t(d.size) <= MaxSize);
278 return d.size;
279 }
280#if QT_DEPRECATED_SINCE(6, 4)
281 QT_DEPRECATED_VERSION_X_6_4("Use size() or length() instead.")
282 constexpr qsizetype count() const { return size(); }
283#endif
284 constexpr qsizetype length() const noexcept { return size(); }
285 constexpr bool isEmpty() const noexcept { return size() == 0; }
286 void resize(qsizetype size);
287 void resize(qsizetype size, QChar fillChar);
288 void resizeForOverwrite(qsizetype size);
289
290 QString &fill(QChar c, qsizetype size = -1);
291 void truncate(qsizetype pos);
292 void chop(qsizetype n);
293
294 QString &slice(qsizetype pos)
295 { verify(pos, 0); return remove(0, pos); }
296 QString &slice(qsizetype pos, qsizetype n)
297 {
298 verify(pos, n);
299 if (isNull())
300 return *this;
301 resize(pos + n);
302 return remove(0, pos);
303 }
304
305 inline qsizetype capacity() const;
306 inline void reserve(qsizetype size);
307 inline void squeeze();
308
309 inline const QChar *unicode() const;
310 inline QChar *data();
311 inline const QChar *data() const;
312 inline const QChar *constData() const;
313
314 inline void detach();
315 inline bool isDetached() const;
316 inline bool isSharedWith(const QString &other) const { return d.isSharedWith(other.d); }
317 inline void clear();
318
319 inline const QChar at(qsizetype i) const;
320 inline const QChar operator[](qsizetype i) const;
321 [[nodiscard]] inline QChar &operator[](qsizetype i);
322
323 [[nodiscard]] inline QChar front() const { return at(0); }
324 [[nodiscard]] inline QChar &front();
325 [[nodiscard]] inline QChar back() const { return at(size() - 1); }
326 [[nodiscard]] inline QChar &back();
327
328#if QT_CORE_REMOVED_SINCE(6, 9)
329 [[nodiscard]] QString arg(qlonglong a, int fieldwidth=0, int base=10,
330 QChar fillChar = u' ') const;
331 [[nodiscard]] QString arg(qulonglong a, int fieldwidth=0, int base=10,
332 QChar fillChar = u' ') const;
333 [[nodiscard]] inline QString arg(long a, int fieldwidth=0, int base=10,
334 QChar fillChar = u' ') const;
335 [[nodiscard]] inline QString arg(ulong a, int fieldwidth=0, int base=10,
336 QChar fillChar = u' ') const;
337 [[nodiscard]] inline QString arg(int a, int fieldWidth = 0, int base = 10,
338 QChar fillChar = u' ') const;
339 [[nodiscard]] inline QString arg(uint a, int fieldWidth = 0, int base = 10,
340 QChar fillChar = u' ') const;
341 [[nodiscard]] inline QString arg(short a, int fieldWidth = 0, int base = 10,
342 QChar fillChar = u' ') const;
343 [[nodiscard]] inline QString arg(ushort a, int fieldWidth = 0, int base = 10,
344 QChar fillChar = u' ') const;
345 [[nodiscard]] QString arg(double a, int fieldWidth = 0, char format = 'g', int precision = -1,
346 QChar fillChar = u' ') const;
347 [[nodiscard]] QString arg(char a, int fieldWidth = 0,
348 QChar fillChar = u' ') const;
349 [[nodiscard]] QString arg(QChar a, int fieldWidth = 0,
350 QChar fillChar = u' ') const;
351 [[nodiscard]] QString arg(const QString &a, int fieldWidth = 0,
352 QChar fillChar = u' ') const;
353 [[nodiscard]] QString arg(QStringView a, int fieldWidth = 0,
354 QChar fillChar = u' ') const;
355 [[nodiscard]] QString arg(QLatin1StringView a, int fieldWidth = 0,
356 QChar fillChar = u' ') const;
357#endif
358
359 template <typename T, if_integral_non_char<T> = true>
360 [[nodiscard]] QString arg(T a, int fieldWidth = 0, int base = 10,
361 QChar fillChar = u' ') const
362 {
363 using U = typename std::conditional<
364 // underlying_type_t<non-enum> is UB in C++17/SFINAE in C++20, so wrap:
365 std::is_enum_v<T>, std::underlying_type<T>,
366 q20::type_identity<T>
367 >::type::type;
368 if constexpr (std::is_signed_v<U>)
369 return arg_impl(qlonglong(a), fieldWidth, base, fillChar);
370 else
371 return arg_impl(qulonglong(a), fieldWidth, base, fillChar);
372 }
373
374 template <typename T, if_floating_point<T> = true>
375 [[nodiscard]] QString arg(T a, int fieldWidth = 0, char format = 'g', int precision = -1,
376 QChar fillChar = u' ') const
377 { return arg_impl(double(a), fieldWidth, format, precision, fillChar); }
378
379 template <typename T, if_string_like<T> = true>
380 [[nodiscard]] QString arg(const T &a, int fieldWidth = 0, QChar fillChar = u' ') const
381 { return arg_impl(QAnyStringView(a), fieldWidth, fillChar); }
382
383private:
384 QString arg_impl(qlonglong a, int fieldwidth, int base, QChar fillChar) const;
385 QString arg_impl(qulonglong a, int fieldwidth, int base, QChar fillChar) const;
386 QString arg_impl(double a, int fieldWidth, char format, int precision, QChar fillChar) const;
387 QString arg_impl(QAnyStringView a, int fieldWidth, QChar fillChar) const;
388
389public:
390 template <typename...Args>
391 [[nodiscard]]
392#ifdef Q_QDOC
393 QString
394#else
395 typename std::enable_if<
396 sizeof...(Args) >= 2 && std::conjunction_v<is_string_like<Args>...>,
397 QString
398 >::type
399#endif
400 arg(Args &&...args) const
401 { return qToStringViewIgnoringNull(*this).arg(std::forward<Args>(args)...); }
402
403 static QString vasprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(1, 0);
404 static QString asprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
405
406 [[nodiscard]] QT_CORE_INLINE_SINCE(6, 8)
407 qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
408 [[nodiscard]] QT_CORE_INLINE_SINCE(6, 12)
409 qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
410 [[nodiscard]] QT_CORE_INLINE_SINCE(6, 12)
411 qsizetype indexOf(const QString &s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
412 [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
413 { return QStringView(begin(), size()).indexOf(s, from, cs); }
414 [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
415 { return lastIndexOf(c, -1, cs); }
416 [[nodiscard]] QT_CORE_INLINE_SINCE(6, 8)
417 qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
418 [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
419 { return lastIndexOf(s, size(), cs); }
420 [[nodiscard]] QT_CORE_INLINE_SINCE(6, 12)
421 qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
422 [[nodiscard]] qsizetype lastIndexOf(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
423 { return lastIndexOf(s, size(), cs); }
424 [[nodiscard]] QT_CORE_INLINE_SINCE(6, 12)
425 qsizetype lastIndexOf(const QString &s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
426
427 [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
428 { return lastIndexOf(s, size(), cs); }
429 [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
430 { return QStringView(begin(), size()).lastIndexOf(s, from, cs); }
431
432 [[nodiscard]] inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
433 [[nodiscard]] inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
434 [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
435 [[nodiscard]] inline bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
436 [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
437 [[nodiscard]] qsizetype count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
438 [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
439
440#if QT_CONFIG(regularexpression)
441 [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0,
442 QRegularExpressionMatch *rmatch = nullptr) const;
443#ifdef Q_QDOC
444 [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
445#else
446 // prevent an ambiguity when called like this: lastIndexOf(re, 0)
447 template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false>
448 [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const
449 { return lastIndexOf(re, size(), rmatch); }
450#endif
451 [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from,
452 QRegularExpressionMatch *rmatch = nullptr) const;
453 [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
454 [[nodiscard]] qsizetype count(const QRegularExpression &re) const;
455#endif
456
457 enum SectionFlag {
458 SectionDefault = 0x00,
459 SectionSkipEmpty = 0x01,
460 SectionIncludeLeadingSep = 0x02,
461 SectionIncludeTrailingSep = 0x04,
462 SectionCaseInsensitiveSeps = 0x08
463 };
464 Q_DECLARE_FLAGS(SectionFlags, SectionFlag)
465
466 [[nodiscard]] inline QString section(QChar sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
467 [[nodiscard]] QString section(const QString &in_sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
468#if QT_CONFIG(regularexpression)
469 [[nodiscard]] QString section(const QRegularExpression &re, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
470#endif
471
472#if QT_CORE_REMOVED_SINCE(6, 7)
473 QString left(qsizetype n) const;
474 QString right(qsizetype n) const;
475 QString mid(qsizetype position, qsizetype n = -1) const;
476
477 QString first(qsizetype n) const;
478 QString last(qsizetype n) const;
479 QString sliced(qsizetype pos) const;
480 QString sliced(qsizetype pos, qsizetype n) const;
481 QString chopped(qsizetype n) const;
482#else
483 [[nodiscard]] QString left(qsizetype n) const &
484 {
485 if (size_t(n) >= size_t(size()))
486 return *this;
487 return first(n);
488 }
489 [[nodiscard]] QString left(qsizetype n) &&
490 {
491 if (size_t(n) >= size_t(size()))
492 return std::move(*this);
493 return std::move(*this).first(n);
494 }
495 [[nodiscard]] QString right(qsizetype n) const &
496 {
497 if (size_t(n) >= size_t(size()))
498 return *this;
499 return last(n);
500 }
501 [[nodiscard]] QString right(qsizetype n) &&
502 {
503 if (size_t(n) >= size_t(size()))
504 return std::move(*this);
505 return std::move(*this).last(n);
506 }
507 [[nodiscard]] QString mid(qsizetype position, qsizetype n = -1) const &;
508 [[nodiscard]] QString mid(qsizetype position, qsizetype n = -1) &&;
509
510 [[nodiscard]] QString first(qsizetype n) const &
511 { verify(0, n); return sliced(0, n); }
512 [[nodiscard]] QString last(qsizetype n) const &
513 { verify(0, n); return sliced(size() - n, n); }
514 [[nodiscard]] QString sliced(qsizetype pos) const &
515 { verify(pos, 0); return sliced(pos, size() - pos); }
516 [[nodiscard]] QString sliced(qsizetype pos, qsizetype n) const &
517 { verify(pos, n); return QString(begin() + pos, n); }
518 [[nodiscard]] QString chopped(qsizetype n) const &
519 { verify(0, n); return sliced(0, size() - n); }
520
521 [[nodiscard]] QString first(qsizetype n) &&
522 {
523 verify(0, n);
524 resize(n); // may detach and allocate memory
525 return std::move(*this);
526 }
527 [[nodiscard]] QString last(qsizetype n) &&
528 { verify(0, n); return sliced_helper(*this, size() - n, n); }
529 [[nodiscard]] QString sliced(qsizetype pos) &&
530 { verify(pos, 0); return sliced_helper(*this, pos, size() - pos); }
531 [[nodiscard]] QString sliced(qsizetype pos, qsizetype n) &&
532 { verify(pos, n); return sliced_helper(*this, pos, n); }
533 [[nodiscard]] QString chopped(qsizetype n) &&
534 { verify(0, n); chop(n); return std::move(*this); }
535#endif
536 bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
537 [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
538 { return QStringView(begin(), size()).startsWith(s, cs); }
539 bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
540 bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
541
542 bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
543 [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
544 { return QStringView(begin(), size()).endsWith(s, cs); }
545 bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
546 bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
547
548 bool isUpper() const;
549 bool isLower() const;
550
551 [[nodiscard]] QString leftJustified(qsizetype width, QChar fill = u' ', bool trunc = false) const;
552 [[nodiscard]] QString rightJustified(qsizetype width, QChar fill = u' ', bool trunc = false) const;
553
554#if !defined(Q_QDOC)
555 [[nodiscard]] QString toLower() const &
556 { return toLower_helper(*this); }
557 [[nodiscard]] QString toLower() &&
558 { return toLower_helper(*this); }
559 [[nodiscard]] QString toUpper() const &
560 { return toUpper_helper(*this); }
561 [[nodiscard]] QString toUpper() &&
562 { return toUpper_helper(*this); }
563 [[nodiscard]] QString toCaseFolded() const &
564 { return toCaseFolded_helper(*this); }
565 [[nodiscard]] QString toCaseFolded() &&
566 { return toCaseFolded_helper(*this); }
567 [[nodiscard]] QString trimmed() const &
568 { return trimmed_helper(*this); }
569 [[nodiscard]] QString trimmed() &&
570 { return trimmed_helper(*this); }
571 [[nodiscard]] QString simplified() const &
572 { return simplified_helper(*this); }
573 [[nodiscard]] QString simplified() &&
574 { return simplified_helper(*this); }
575#else
576 [[nodiscard]] QString toLower() const;
577 [[nodiscard]] QString toUpper() const;
578 [[nodiscard]] QString toCaseFolded() const;
579 [[nodiscard]] QString trimmed() const;
580 [[nodiscard]] QString simplified() const;
581#endif
582 [[nodiscard]] QString toHtmlEscaped() const;
583
584 QString &insert(qsizetype i, QChar c);
585 QString &insert(qsizetype i, const QChar *uc, qsizetype len);
586 inline QString &insert(qsizetype i, const QString &s) { return insert(i, s.constData(), s.size()); }
587 inline QString &insert(qsizetype i, QStringView v) { return insert(i, v.data(), v.size()); }
588 QString &insert(qsizetype i, QLatin1StringView s);
589 QString &insert(qsizetype i, QUtf8StringView s);
590
591 QString &append(QChar c);
592 QString &append(const QChar *uc, qsizetype len);
593 QString &append(const QString &s);
594 inline QString &append(QStringView v) { return append(v.data(), v.size()); }
595 QString &append(QLatin1StringView s);
596 QString &append(QUtf8StringView s);
597
598 inline QString &prepend(QChar c) { return insert(0, c); }
599 inline QString &prepend(const QChar *uc, qsizetype len) { return insert(0, uc, len); }
600 inline QString &prepend(const QString &s) { return insert(0, s); }
601 inline QString &prepend(QStringView v) { return prepend(v.data(), v.size()); }
602 inline QString &prepend(QLatin1StringView s) { return insert(0, s); }
603 QString &prepend(QUtf8StringView s) { return insert(0, s); }
604
605 QString &assign(QAnyStringView s);
606 inline QString &assign(qsizetype n, QChar c)
607 {
608 Q_ASSERT(n >= 0);
609 return fill(c, n);
610 }
611 template <typename InputIterator, if_compatible_iterator<InputIterator> = true>
612 QString &assign(InputIterator first, InputIterator last)
613 {
614 using V = typename std::iterator_traits<InputIterator>::value_type;
615 constexpr bool IsL1C = std::is_same_v<std::remove_cv_t<V>, QLatin1Char>;
616 constexpr bool IsFwdIt = std::is_convertible_v<
617 typename std::iterator_traits<InputIterator>::iterator_category,
618 std::forward_iterator_tag
619 >;
620
621 if constexpr (is_contiguous_iterator_v<InputIterator>) {
622 const auto p = q20::to_address(first);
623 const auto len = qsizetype(last - first);
624 if constexpr (IsL1C)
625 return assign(QLatin1StringView(reinterpret_cast<const char*>(p), len));
626 else if constexpr (sizeof(V) == 4)
627 return assign_helper(p, len);
628 else
629 return assign(QAnyStringView(p, len));
630 } else if constexpr (sizeof(V) == 4) { // non-contiguous iterator, feed data piecemeal
631 resize(0);
632 if constexpr (IsFwdIt) {
633 const qsizetype requiredCapacity = 2 * std::distance(first, last);
634 reserve(requiredCapacity);
635 }
636 while (first != last) {
637 append(QChar::fromUcs4(*first));
638 ++first;
639 }
640 return *this;
641 } else if constexpr (QtPrivate::IsCompatibleChar8Type<V>::value) {
642 assign_helper_char8(first, last);
643 if (d.constAllocatedCapacity())
644 d.data()[d.size] = u'\0';
645 return *this;
646 } else {
647 d->assign(first, last, [](QChar ch) noexcept -> char16_t { return ch.unicode(); });
648 if (d.constAllocatedCapacity())
649 d.data()[d.size] = u'\0';
650 return *this;
651 }
652 }
653
654 inline QString &operator+=(QChar c) { return append(c); }
655
656 inline QString &operator+=(const QString &s) { return append(s); }
657 inline QString &operator+=(QStringView v) { return append(v); }
658 inline QString &operator+=(QLatin1StringView s) { return append(s); }
659 QString &operator+=(QUtf8StringView s) { return append(s); }
660
661#if defined(QT_RESTRICTED_CAST_FROM_ASCII)
662 template <qsizetype N>
663 QString &insert(qsizetype i, const char (&ch)[N]) { return insert(i, QUtf8StringView(ch)); }
664 template <qsizetype N>
665 QString &append(const char (&ch)[N]) { return append(QUtf8StringView(ch)); }
666 template <qsizetype N>
667 QString &prepend(const char (&ch)[N]) { return prepend(QUtf8StringView(ch)); }
668 template <qsizetype N>
669 QString &operator+=(const char (&ch)[N]) { return append(QUtf8StringView(ch)); }
670#endif
671
672 QString &remove(qsizetype i, qsizetype len);
673 QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive);
674 QString &remove(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
675 QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
676
677 QString &removeAt(qsizetype pos)
678 { return size_t(pos) < size_t(size()) ? remove(pos, 1) : *this; }
679 QString &removeFirst() { return !isEmpty() ? remove(0, 1) : *this; }
680 QString &removeLast() { return !isEmpty() ? remove(size() - 1, 1) : *this; }
681
682 template <typename Predicate>
683 QString &removeIf(Predicate pred)
684 {
685 removeIf_helper(pred);
686 return *this;
687 }
688
689 QString &replace(qsizetype i, qsizetype len, QChar after);
690 QString &replace(qsizetype i, qsizetype len, const QChar *s, qsizetype slen);
691 QString &replace(qsizetype i, qsizetype len, const QString &after);
692 QString &replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
693 QString &replace(const QChar *before, qsizetype blen, const QChar *after, qsizetype alen, Qt::CaseSensitivity cs = Qt::CaseSensitive);
694 QString &replace(QLatin1StringView before, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
695 QString &replace(QLatin1StringView before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
696 QString &replace(const QString &before, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
697 QString &replace(const QString &before, const QString &after,
698 Qt::CaseSensitivity cs = Qt::CaseSensitive);
699 QString &replace(QChar c, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
700 QString &replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
701#if QT_CONFIG(regularexpression)
702 QString &replace(const QRegularExpression &re, const QString &after);
703 inline QString &remove(const QRegularExpression &re)
704 { return replace(re, QString()); }
705#endif
706
707public:
708 [[nodiscard]]
709 QStringList split(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
710 Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
711 [[nodiscard]]
712 QStringList split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
713 Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
714#ifndef QT_NO_REGULAREXPRESSION
715 [[nodiscard]]
716 QStringList split(const QRegularExpression &sep,
717 Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
718#endif
719
720 template <typename Needle, typename...Flags>
721 [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) const &
722 noexcept(noexcept(qTokenize(std::declval<const QString &>(), std::forward<Needle>(needle), flags...)))
723 -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
724 { return qTokenize(qToStringViewIgnoringNull(*this), std::forward<Needle>(needle), flags...); }
725
726 template <typename Needle, typename...Flags>
727 [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) const &&
728 noexcept(noexcept(qTokenize(std::declval<const QString>(), std::forward<Needle>(needle), flags...)))
729 -> decltype(qTokenize(std::move(*this), std::forward<Needle>(needle), flags...))
730 { return qTokenize(std::move(*this), std::forward<Needle>(needle), flags...); }
731
732 template <typename Needle, typename...Flags>
733 [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) &&
734 noexcept(noexcept(qTokenize(std::declval<QString>(), std::forward<Needle>(needle), flags...)))
735 -> decltype(qTokenize(std::move(*this), std::forward<Needle>(needle), flags...))
736 { return qTokenize(std::move(*this), std::forward<Needle>(needle), flags...); }
737
738
739 enum NormalizationForm {
740 NormalizationForm_D,
741 NormalizationForm_C,
742 NormalizationForm_KD,
743 NormalizationForm_KC
744 };
745 [[nodiscard]] QString normalized(NormalizationForm mode, QChar::UnicodeVersion version = QChar::Unicode_Unassigned) const;
746
747 [[nodiscard]] QString repeated(qsizetype times) const;
748
749 const ushort *utf16() const; // ### Qt 7 char16_t
750 [[nodiscard]] QString nullTerminated() const &;
751 [[nodiscard]] QString nullTerminated() &&;
752 QString &nullTerminate();
753
754#if !defined(Q_QDOC)
755 [[nodiscard]] QByteArray toLatin1() const &
756 { return toLatin1_helper(*this); }
757 [[nodiscard]] QByteArray toLatin1() &&
758 { return toLatin1_helper_inplace(*this); }
759 [[nodiscard]] QByteArray toUtf8() const &
760 { return toUtf8_helper(*this); }
761 [[nodiscard]] QByteArray toUtf8() &&
762 { return toUtf8_helper(*this); }
763 [[nodiscard]] QByteArray toLocal8Bit() const &
764 { return toLocal8Bit_helper(isNull() ? nullptr : constData(), size()); }
765 [[nodiscard]] QByteArray toLocal8Bit() &&
766 { return toLocal8Bit_helper(isNull() ? nullptr : constData(), size()); }
767#else
768 [[nodiscard]] QByteArray toLatin1() const;
769 [[nodiscard]] QByteArray toUtf8() const;
770 [[nodiscard]] QByteArray toLocal8Bit() const;
771#endif
772 [[nodiscard]] QList<uint> toUcs4() const; // ### Qt 7 char32_t
773
774 // note - this are all inline so we can benefit from strlen() compile time optimizations
775 static QString fromLatin1(QByteArrayView ba);
776 Q_WEAK_OVERLOAD
777 static inline QString fromLatin1(const QByteArray &ba) { return fromLatin1(QByteArrayView(ba)); }
778 static inline QString fromLatin1(const char *str, qsizetype size)
779 {
780 return fromLatin1(QByteArrayView(str, !str || size < 0 ? qstrlen(str) : size));
781 }
782 static QString fromUtf8(QByteArrayView utf8);
783 Q_WEAK_OVERLOAD
784 static inline QString fromUtf8(const QByteArray &ba) { return fromUtf8(QByteArrayView(ba)); }
785 static inline QString fromUtf8(const char *utf8, qsizetype size)
786 {
787 return fromUtf8(QByteArrayView(utf8, !utf8 || size < 0 ? qstrlen(utf8) : size));
788 }
789#if defined(__cpp_char8_t) || defined(Q_QDOC)
790 Q_WEAK_OVERLOAD
791 static inline QString fromUtf8(const char8_t *str)
792 { return fromUtf8(reinterpret_cast<const char *>(str)); }
793 Q_WEAK_OVERLOAD
794 static inline QString fromUtf8(const char8_t *str, qsizetype size)
795 { return fromUtf8(reinterpret_cast<const char *>(str), size); }
796#endif
797 static QString fromLocal8Bit(QByteArrayView ba);
798 Q_WEAK_OVERLOAD
799 static inline QString fromLocal8Bit(const QByteArray &ba) { return fromLocal8Bit(QByteArrayView(ba)); }
800 static inline QString fromLocal8Bit(const char *str, qsizetype size)
801 {
802 return fromLocal8Bit(QByteArrayView(str, !str || size < 0 ? qstrlen(str) : size));
803 }
804 static QString fromUtf16(const char16_t *, qsizetype size = -1);
805 static QString fromUcs4(const char32_t *, qsizetype size = -1);
806 static QString fromRawData(const char16_t *unicode, qsizetype size)
807 {
808 return QString(DataPointer::fromRawData(unicode, size));
809 }
810 QT_CORE_INLINE_SINCE(6, 10)
811 static QString fromRawData(const QChar *, qsizetype size);
812
813#if QT_DEPRECATED_SINCE(6, 0)
814 QT_DEPRECATED_VERSION_X_6_0("Use char16_t* overload.")
815 static QString fromUtf16(const ushort *str, qsizetype size = -1)
816 { return fromUtf16(reinterpret_cast<const char16_t *>(str), size); }
817 QT_DEPRECATED_VERSION_X_6_0("Use char32_t* overload.")
818 static QString fromUcs4(const uint *str, qsizetype size = -1)
819 { return fromUcs4(reinterpret_cast<const char32_t *>(str), size); }
820#endif
821
822 inline qsizetype toWCharArray(wchar_t *array) const;
823 [[nodiscard]] static inline QString fromWCharArray(const wchar_t *string, qsizetype size = -1);
824
825 QString &setRawData(const QChar *unicode, qsizetype size);
826 QString &setUnicode(const QChar *unicode, qsizetype size);
827 Q_WEAK_OVERLOAD
828 QString &setUnicode(const char16_t *utf16, qsizetype size)
829 { return setUnicode(reinterpret_cast<const QChar *>(utf16), size); }
830 QString &setUtf16(const char16_t *utf16, qsizetype size)
831 { return setUnicode(reinterpret_cast<const QChar *>(utf16), size); }
832
833#if !QT_CORE_REMOVED_SINCE(6, 9)
834 Q_WEAK_OVERLOAD
835#endif
836 QString &setUtf16(const ushort *autf16, qsizetype asize)
837 { return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
838
839 int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
840 int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
841 inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
842 int compare(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
843 { return compare(QStringView{&ch, 1}, cs); }
844
845 static inline int compare(const QString &s1, const QString &s2,
846 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
847 { return s1.compare(s2, cs); }
848
849 static inline int compare(const QString &s1, QLatin1StringView s2,
850 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
851 { return s1.compare(s2, cs); }
852 static inline int compare(QLatin1StringView s1, const QString &s2,
853 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
854 { return -s2.compare(s1, cs); }
855 static int compare(const QString &s1, QStringView s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
856 { return s1.compare(s2, cs); }
857 static int compare(QStringView s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
858 { return -s2.compare(s1, cs); }
859
860 int localeAwareCompare(const QString& s) const;
861 inline int localeAwareCompare(QStringView s) const;
862 static int localeAwareCompare(const QString& s1, const QString& s2)
863 { return s1.localeAwareCompare(s2); }
864
865 static inline int localeAwareCompare(QStringView s1, QStringView s2);
866
867 short toShort(bool *ok=nullptr, int base=10) const
868 { return toIntegral_helper<short>(*this, ok, base); }
869 ushort toUShort(bool *ok=nullptr, int base=10) const
870 { return toIntegral_helper<ushort>(*this, ok, base); }
871 int toInt(bool *ok=nullptr, int base=10) const
872 { return toIntegral_helper<int>(*this, ok, base); }
873 uint toUInt(bool *ok=nullptr, int base=10) const
874 { return toIntegral_helper<uint>(*this, ok, base); }
875 long toLong(bool *ok=nullptr, int base=10) const
876 { return toIntegral_helper<long>(*this, ok, base); }
877 ulong toULong(bool *ok=nullptr, int base=10) const
878 { return toIntegral_helper<ulong>(*this, ok, base); }
879 QT_CORE_INLINE_SINCE(6, 5)
880 qlonglong toLongLong(bool *ok=nullptr, int base=10) const;
881 QT_CORE_INLINE_SINCE(6, 5)
882 qulonglong toULongLong(bool *ok=nullptr, int base=10) const;
883 float toFloat(bool *ok=nullptr) const;
884 double toDouble(bool *ok=nullptr) const;
885
886 inline QString &setNum(short, int base=10);
887 inline QString &setNum(ushort, int base=10);
888 inline QString &setNum(int, int base=10);
889 inline QString &setNum(uint, int base=10);
890 inline QString &setNum(long, int base=10);
891 inline QString &setNum(ulong, int base=10);
892 QString &setNum(qlonglong, int base=10);
893 QString &setNum(qulonglong, int base=10);
894 inline QString &setNum(float, char format='g', int precision=6);
895 QString &setNum(double, char format='g', int precision=6);
896
897 static QString number(int, int base=10);
898 static QString number(uint, int base=10);
899 static QString number(long, int base=10);
900 static QString number(ulong, int base=10);
901 static QString number(qlonglong, int base=10);
902 static QString number(qulonglong, int base=10);
903 static QString number(double, char format='g', int precision=6);
904
905 friend bool comparesEqual(const QString &s1, const QString &s2) noexcept
906 { return comparesEqual(QStringView(s1), QStringView(s2)); }
907 friend Qt::strong_ordering compareThreeWay(const QString &s1, const QString &s2) noexcept
908 { return compareThreeWay(QStringView(s1), QStringView(s2)); }
909 Q_DECLARE_STRONGLY_ORDERED(QString)
910
911 Q_WEAK_OVERLOAD
912 friend bool comparesEqual(const QString &s1, QUtf8StringView s2) noexcept
913 { return QtPrivate::equalStrings(s1, s2); }
914 Q_WEAK_OVERLOAD
915 friend Qt::strong_ordering compareThreeWay(const QString &s1, QUtf8StringView s2) noexcept
916 {
917 const int res = QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive);
918 return Qt::compareThreeWay(res, 0);
919 }
920 Q_DECLARE_STRONGLY_ORDERED(QString, QUtf8StringView, Q_WEAK_OVERLOAD)
921
922#ifdef __cpp_char8_t
923 friend bool comparesEqual(const QString &s1, const char8_t *s2) noexcept
924 { return comparesEqual(s1, QUtf8StringView(s2)); }
925 friend Qt::strong_ordering compareThreeWay(const QString &s1, const char8_t *s2) noexcept
926 { return compareThreeWay(s1, QUtf8StringView(s2)); }
927 Q_DECLARE_STRONGLY_ORDERED(QString, const char8_t *)
928#endif // __cpp_char8_t
929
930 friend bool comparesEqual(const QString &s1, QLatin1StringView s2) noexcept
931 { return (s1.size() == s2.size()) && QtPrivate::equalStrings(s1, s2); }
932 friend Qt::strong_ordering
933 compareThreeWay(const QString &s1, QLatin1StringView s2) noexcept
934 {
935 const int res = QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive);
936 return Qt::compareThreeWay(res, 0);
937 }
938 Q_DECLARE_STRONGLY_ORDERED(QString, QLatin1StringView)
939
940 // Check isEmpty() instead of isNull() for backwards compatibility.
941 friend bool comparesEqual(const QString &s1, std::nullptr_t) noexcept
942 { return s1.isEmpty(); }
943 friend Qt::strong_ordering compareThreeWay(const QString &s1, std::nullptr_t) noexcept
944 { return s1.isEmpty() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; }
945 Q_DECLARE_STRONGLY_ORDERED(QString, std::nullptr_t)
946
947 friend bool comparesEqual(const QString &s1, const char16_t *s2) noexcept
948 { return comparesEqual(s1, QStringView(s2)); }
949 friend Qt::strong_ordering compareThreeWay(const QString &s1, const char16_t *s2) noexcept
950 { return compareThreeWay(s1, QStringView(s2)); }
951 Q_DECLARE_STRONGLY_ORDERED(QString, const char16_t *)
952
953 // QChar <> QString
954 friend bool comparesEqual(const QString &lhs, QChar rhs) noexcept
955 { return lhs.size() == 1 && rhs == lhs.front(); }
956 friend Qt::strong_ordering compareThreeWay(const QString &lhs, QChar rhs) noexcept
957 {
958 const int res = compare_helper(lhs.data(), lhs.size(), &rhs, 1);
959 return Qt::compareThreeWay(res, 0);
960 }
961 Q_DECLARE_STRONGLY_ORDERED(QString, QChar)
962
963 // ASCII compatibility
964#if defined(QT_RESTRICTED_CAST_FROM_ASCII)
965 template <qsizetype N>
966 inline QString(const char (&ch)[N])
967 : QString(fromUtf8(ch))
968 {}
969 template <qsizetype N>
970 QString(char (&)[N]) = delete;
971 template <qsizetype N>
972 inline QString &operator=(const char (&ch)[N])
973 { return (*this = fromUtf8(ch, N - 1)); }
974 template <qsizetype N>
975 QString &operator=(char (&)[N]) = delete;
976#endif
977#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
978 QT_ASCII_CAST_WARN inline QString(const char *ch)
979 : QString(fromUtf8(ch))
980 {}
981 QT_ASCII_CAST_WARN inline QString(const QByteArray &a)
982 : QString(fromUtf8(a))
983 {}
984 QT_ASCII_CAST_WARN inline QString &operator=(const char *ch)
985 {
986 if (!ch) {
987 clear();
988 return *this;
989 }
990 return assign(ch);
991 }
992 QT_ASCII_CAST_WARN inline QString &operator=(const QByteArray &a)
993 {
994 if (a.isNull()) {
995 clear();
996 return *this;
997 }
998 return assign(a);
999 }
1000 // these are needed, so it compiles with STL support enabled
1001 QT_ASCII_CAST_WARN inline QString &prepend(const char *s)
1002 { return prepend(QUtf8StringView(s)); }
1003 QT_ASCII_CAST_WARN inline QString &prepend(const QByteArray &s)
1004 { return prepend(QUtf8StringView(s)); }
1005 QT_ASCII_CAST_WARN inline QString &append(const char *s)
1006 { return append(QUtf8StringView(s)); }
1007 QT_ASCII_CAST_WARN inline QString &append(const QByteArray &s)
1008 { return append(QUtf8StringView(s)); }
1009 QT_ASCII_CAST_WARN inline QString &insert(qsizetype i, const char *s)
1010 { return insert(i, QUtf8StringView(s)); }
1011 QT_ASCII_CAST_WARN inline QString &insert(qsizetype i, const QByteArray &s)
1012 { return insert(i, QUtf8StringView(s)); }
1013 QT_ASCII_CAST_WARN inline QString &operator+=(const char *s)
1014 { return append(QUtf8StringView(s)); }
1015 QT_ASCII_CAST_WARN inline QString &operator+=(const QByteArray &s)
1016 { return append(QUtf8StringView(s)); }
1017
1018#if QT_CORE_REMOVED_SINCE(6, 8)
1019 QT_ASCII_CAST_WARN inline bool operator==(const char *s) const;
1020 QT_ASCII_CAST_WARN inline bool operator!=(const char *s) const;
1021 QT_ASCII_CAST_WARN inline bool operator<(const char *s) const;
1022 QT_ASCII_CAST_WARN inline bool operator<=(const char *s) const;
1023 QT_ASCII_CAST_WARN inline bool operator>(const char *s) const;
1024 QT_ASCII_CAST_WARN inline bool operator>=(const char *s) const;
1025
1026 QT_ASCII_CAST_WARN inline bool operator==(const QByteArray &s) const;
1027 QT_ASCII_CAST_WARN inline bool operator!=(const QByteArray &s) const;
1028 QT_ASCII_CAST_WARN inline bool operator<(const QByteArray &s) const;
1029 QT_ASCII_CAST_WARN inline bool operator>(const QByteArray &s) const;
1030 QT_ASCII_CAST_WARN inline bool operator<=(const QByteArray &s) const;
1031 QT_ASCII_CAST_WARN inline bool operator>=(const QByteArray &s) const;
1032#else
1033 friend bool comparesEqual(const QString &lhs, QByteArrayView rhs) noexcept
1034 {
1035 return QString::compare_helper(lhs.constData(), lhs.size(),
1036 rhs.constData(), rhs.size()) == 0;
1037 }
1038 friend Qt::strong_ordering
1039 compareThreeWay(const QString &lhs, QByteArrayView rhs) noexcept
1040 {
1041 const int res = QString::compare_helper(lhs.constData(), lhs.size(),
1042 rhs.constData(), rhs.size());
1043 return Qt::compareThreeWay(res, 0);
1044 }
1045 Q_DECLARE_STRONGLY_ORDERED(QString, QByteArrayView, QT_ASCII_CAST_WARN)
1046
1047 friend bool comparesEqual(const QString &lhs, const QByteArray &rhs) noexcept
1048 { return comparesEqual(lhs, QByteArrayView(rhs)); }
1049 friend Qt::strong_ordering
1050 compareThreeWay(const QString &lhs, const QByteArray &rhs) noexcept
1051 {
1052 return compareThreeWay(lhs, QByteArrayView(rhs));
1053 }
1054 Q_DECLARE_STRONGLY_ORDERED(QString, QByteArray, QT_ASCII_CAST_WARN)
1055
1056 friend bool comparesEqual(const QString &lhs, const char *rhs) noexcept
1057 { return comparesEqual(lhs, QByteArrayView(rhs)); }
1058 friend Qt::strong_ordering
1059 compareThreeWay(const QString &lhs, const char *rhs) noexcept
1060 {
1061 return compareThreeWay(lhs, QByteArrayView(rhs));
1062 }
1063 Q_DECLARE_STRONGLY_ORDERED(QString, const char *, QT_ASCII_CAST_WARN)
1064#endif // QT_CORE_REMOVED_SINCE(6, 8)
1065
1066#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1067
1068 typedef QChar *iterator;
1069 typedef const QChar *const_iterator;
1070 typedef iterator Iterator;
1071 typedef const_iterator ConstIterator;
1072 typedef std::reverse_iterator<iterator> reverse_iterator;
1073 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1074 inline iterator begin();
1075 inline const_iterator begin() const;
1076 inline const_iterator cbegin() const;
1077 inline const_iterator constBegin() const;
1078 inline iterator end();
1079 inline const_iterator end() const;
1080 inline const_iterator cend() const;
1081 inline const_iterator constEnd() const;
1082 reverse_iterator rbegin() { return reverse_iterator(end()); }
1083 reverse_iterator rend() { return reverse_iterator(begin()); }
1084 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
1085 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
1086 const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
1087 const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
1088
1089 // STL compatibility
1090 typedef qsizetype size_type;
1091 typedef qptrdiff difference_type;
1092 typedef const QChar & const_reference;
1093 typedef QChar & reference;
1094 typedef QChar *pointer;
1095 typedef const QChar *const_pointer;
1096 typedef QChar value_type;
1097 inline void push_back(QChar c) { append(c); }
1098 inline void push_back(const QString &s) { append(s); }
1099 inline void push_front(QChar c) { prepend(c); }
1100 inline void push_front(const QString &s) { prepend(s); }
1101 void shrink_to_fit() { squeeze(); }
1102 iterator erase(const_iterator first, const_iterator last);
1103 inline iterator erase(const_iterator it) { return erase(it, it + 1); }
1104 constexpr qsizetype max_size() const noexcept
1105 {
1106 return maxSize();
1107 }
1108
1109 static inline QString fromStdString(const std::string &s);
1110 std::string toStdString() const;
1111 static inline QString fromStdWString(const std::wstring &s);
1112 inline std::wstring toStdWString() const;
1113
1114 static inline QString fromStdU16String(const std::u16string &s);
1115 inline std::u16string toStdU16String() const;
1116 static inline QString fromStdU32String(const std::u32string &s);
1117 inline std::u32string toStdU32String() const;
1118
1119 Q_IMPLICIT inline operator std::u16string_view() const noexcept;
1120
1121#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
1122 static QString fromCFString(CFStringRef string);
1123 CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
1124 static QString fromNSString(const NSString *string);
1125 NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
1126#endif
1127
1128#if defined(Q_OS_WASM) || defined(Q_QDOC)
1129 static QString fromEcmaString(emscripten::val jsString);
1130 emscripten::val toEcmaString() const;
1131#endif
1132
1133 constexpr bool isNull() const { return d.isNull(); }
1134
1135 bool isRightToLeft() const;
1136 [[nodiscard]] bool isValidUtf16() const noexcept
1137 { return QStringView(*this).isValidUtf16(); }
1138
1139 QString(qsizetype size, Qt::Initialization);
1140 explicit QString(DataPointer &&dd) : d(std::move(dd)) {}
1141
1142private:
1143#if defined(QT_NO_CAST_FROM_ASCII)
1144#define QSTRING_DECL_DELETED_ASCII_OP Q_DECL_EQ_DELETE_X("This function is not available under QT_NO_CAST_FROM_ASCII")
1145 QString &operator+=(const char *s) QSTRING_DECL_DELETED_ASCII_OP;
1146 QString &operator+=(const QByteArray &s) QSTRING_DECL_DELETED_ASCII_OP;
1147 QString(const char *ch) QSTRING_DECL_DELETED_ASCII_OP;
1148 QString(const QByteArray &a) QSTRING_DECL_DELETED_ASCII_OP;
1149 QString &operator=(const char *ch) QSTRING_DECL_DELETED_ASCII_OP;
1150 QString &operator=(const QByteArray &a) QSTRING_DECL_DELETED_ASCII_OP;
1151#undef QSTRING_DECL_DELETED_ASCII_OP
1152#endif
1153
1154 DataPointer d;
1155 static const char16_t _empty;
1156
1157 void reallocData(qsizetype alloc, QArrayData::AllocationOption option);
1158 void reallocGrowData(qsizetype n);
1159 // ### remove once QAnyStringView supports UTF-32:
1160 QString &assign_helper(const char32_t *data, qsizetype len);
1161 // Defined in qstringconverter.h
1162 template <typename InputIterator>
1163 void assign_helper_char8(InputIterator first, InputIterator last);
1164 static int compare_helper(const QChar *data1, qsizetype length1,
1165 const QChar *data2, qsizetype length2,
1166 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
1167 static int compare_helper(const QChar *data1, qsizetype length1,
1168 const char *data2, qsizetype length2,
1169 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
1170 static int localeAwareCompare_helper(const QChar *data1, qsizetype length1,
1171 const QChar *data2, qsizetype length2);
1172 static QString sliced_helper(QString &str, qsizetype pos, qsizetype n);
1173 static QString toLower_helper(const QString &str);
1174 static QString toLower_helper(QString &str);
1175 static QString toUpper_helper(const QString &str);
1176 static QString toUpper_helper(QString &str);
1177 static QString toCaseFolded_helper(const QString &str);
1178 static QString toCaseFolded_helper(QString &str);
1179 static QString trimmed_helper(const QString &str);
1180 static QString trimmed_helper(QString &str);
1181 static QString simplified_helper(const QString &str);
1182 static QString simplified_helper(QString &str);
1183 static QByteArray toLatin1_helper(const QString &);
1184 static QByteArray toLatin1_helper_inplace(QString &);
1185 static QByteArray toUtf8_helper(const QString &);
1186 static QByteArray toLocal8Bit_helper(const QChar *data, qsizetype size);
1187#if QT_CORE_REMOVED_SINCE(6, 6)
1188 static qsizetype toUcs4_helper(const ushort *uc, qsizetype length, uint *out);
1189#endif
1190 static qsizetype toUcs4_helper(const char16_t *uc, qsizetype length, char32_t *out);
1191 static qlonglong toIntegral_helper(QStringView string, bool *ok, int base);
1192 static qulonglong toIntegral_helper(QStringView string, bool *ok, uint base);
1193 template <typename Predicate>
1194 qsizetype removeIf_helper(Predicate pred)
1195 {
1196 const qsizetype result = d->eraseIf(pred);
1197 if (result > 0)
1198 d.data()[d.size] = u'\0';
1199 return result;
1200 }
1201
1202 friend class QStringView;
1203 friend class QByteArray;
1204 friend struct QAbstractConcatenable;
1205 template <typename T> friend qsizetype erase(QString &s, const T &t);
1206 template <typename Predicate> friend qsizetype erase_if(QString &s, Predicate pred);
1207
1208 template <typename T> static
1209 T toIntegral_helper(QStringView string, bool *ok, int base)
1210 {
1211 using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
1212 using Int32 = typename std::conditional<std::is_unsigned<T>::value, uint, int>::type;
1213
1214 // we select the right overload by casting base to int or uint
1215 Int64 val = toIntegral_helper(string, ok, Int32(base));
1216 if (T(val) != val) {
1217 if (ok)
1218 *ok = false;
1219 val = 0;
1220 }
1221 return T(val);
1222 }
1223
1224 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
1225 [[maybe_unused]] qsizetype n = 1) const
1226 {
1227 Q_ASSERT(pos >= 0);
1228 Q_ASSERT(pos <= d.size);
1229 Q_ASSERT(n >= 0);
1230 Q_ASSERT(n <= d.size - pos);
1231 }
1232
1233public:
1234 inline DataPointer &data_ptr() { return d; }
1235 inline const DataPointer &data_ptr() const { return d; }
1236};
1237
1238//
1239// QLatin1StringView inline members that require QUtf8StringView:
1240//
1241
1242int QLatin1StringView::compare(QUtf8StringView other, Qt::CaseSensitivity cs) const noexcept
1243{ return QtPrivate::compareStrings(*this, other, cs); }
1244
1245//
1246// QLatin1StringView inline members that require QString:
1247//
1248
1249QString QLatin1StringView::toString() const { return *this; }
1250
1251//
1252// QStringView inline members that require QUtf8StringView:
1253//
1254
1255int QStringView::compare(QUtf8StringView other, Qt::CaseSensitivity cs) const noexcept
1256{ return QtPrivate::compareStrings(*this, other, cs); }
1257
1258//
1259// QStringView inline members that require QString:
1260//
1261
1262QString QStringView::toString() const
1263{ return QString(*this); }
1264
1265qint64 QStringView::toLongLong(bool *ok, int base) const
1266{ return QString::toIntegral_helper<qint64>(*this, ok, base); }
1267quint64 QStringView::toULongLong(bool *ok, int base) const
1268{ return QString::toIntegral_helper<quint64>(*this, ok, base); }
1269long QStringView::toLong(bool *ok, int base) const
1270{ return QString::toIntegral_helper<long>(*this, ok, base); }
1271ulong QStringView::toULong(bool *ok, int base) const
1272{ return QString::toIntegral_helper<ulong>(*this, ok, base); }
1273int QStringView::toInt(bool *ok, int base) const
1274{ return QString::toIntegral_helper<int>(*this, ok, base); }
1275uint QStringView::toUInt(bool *ok, int base) const
1276{ return QString::toIntegral_helper<uint>(*this, ok, base); }
1277short QStringView::toShort(bool *ok, int base) const
1278{ return QString::toIntegral_helper<short>(*this, ok, base); }
1279ushort QStringView::toUShort(bool *ok, int base) const
1280{ return QString::toIntegral_helper<ushort>(*this, ok, base); }
1281
1282//
1283// QUtf8StringView inline members that require QStringView:
1284//
1285
1286template <bool UseChar8T>
1287int QBasicUtf8StringView<UseChar8T>::compare(QChar other, Qt::CaseSensitivity cs) const noexcept
1288{
1289 return QtPrivate::compareStrings(*this, QStringView(&other, 1), cs);
1290}
1291
1292template <bool UseChar8T>
1293int QBasicUtf8StringView<UseChar8T>::compare(QStringView other, Qt::CaseSensitivity cs) const noexcept
1294{
1295 return QtPrivate::compareStrings(*this, other, cs);
1296}
1297
1298template <bool UseChar8T>
1299[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QChar other) const noexcept
1300{
1301 return QtPrivate::equalStrings(*this, QStringView(&other, 1));
1302}
1303
1304template <bool UseChar8T>
1305[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QStringView other) const noexcept
1306{
1307 return QtPrivate::equalStrings(*this, other);
1308}
1309
1310//
1311// QUtf8StringView inline members that require QString, QL1SV or QBA:
1312//
1313
1314template <bool UseChar8T>
1315QString QBasicUtf8StringView<UseChar8T>::toString() const
1316{
1317 return QString::fromUtf8(data(), size());
1318}
1319
1320template<bool UseChar8T>
1321[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(QLatin1StringView other,
1322 Qt::CaseSensitivity cs) const noexcept
1323{
1324 return QtPrivate::compareStrings(*this, other, cs);
1325}
1326
1327template<bool UseChar8T>
1328[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(const QByteArray &other,
1329 Qt::CaseSensitivity cs) const noexcept
1330{
1331 return QtPrivate::compareStrings(*this,
1332 QBasicUtf8StringView<UseChar8T>(other.data(), other.size()),
1333 cs);
1334}
1335
1336template <bool UseChar8T>
1337[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QLatin1StringView other) const noexcept
1338{
1339 return QtPrivate::equalStrings(*this, other);
1340}
1341
1342template <bool UseChar8T>
1343[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(const QByteArray &other) const noexcept
1344{
1345 return size() == other.size()
1346 && QtPrivate::equalStrings(*this, QBasicUtf8StringView<UseChar8T>(other.data(),
1347 other.size()));
1348}
1349
1350//
1351// QAnyStringView inline members that require QString:
1352//
1353
1354QAnyStringView::QAnyStringView(const QByteArray &str) noexcept
1355 : QAnyStringView{str.begin(), str.size()} {}
1356QAnyStringView::QAnyStringView(const QString &str) noexcept
1357 : QAnyStringView{str.begin(), str.size()} {}
1358
1359QString QAnyStringView::toString() const
1360{ return QtPrivate::convertToQString(*this); }
1361
1362//
1363// QString inline members
1364//
1365QString::QString(QLatin1StringView latin1)
1366 : QString{QString::fromLatin1(latin1.data(), latin1.size())} {}
1367const QChar QString::at(qsizetype i) const
1368{ verify(i, 1); return QChar(d.data()[i]); }
1369const QChar QString::operator[](qsizetype i) const
1370{ verify(i, 1); return QChar(d.data()[i]); }
1371const QChar *QString::unicode() const
1372{ return data(); }
1373const QChar *QString::data() const
1374{
1375#if QT5_NULL_STRINGS == 1
1376 return reinterpret_cast<const QChar *>(d.data() ? d.data() : &_empty);
1377#else
1378 return reinterpret_cast<const QChar *>(d.data());
1379#endif
1380}
1381QChar *QString::data()
1382{
1383 detach();
1384 Q_ASSERT(d.data());
1385 return reinterpret_cast<QChar *>(d.data());
1386}
1387const QChar *QString::constData() const
1388{ return data(); }
1389void QString::detach()
1390{ if (d.needsDetach()) reallocData(d.size, QArrayData::KeepSize); }
1391bool QString::isDetached() const
1392{ return !d.isShared(); }
1393void QString::clear()
1394{ if (!isNull()) *this = QString(); }
1395QString::QString(const QString &other) noexcept : d(other.d)
1396{ }
1397qsizetype QString::capacity() const { return qsizetype(d.constAllocatedCapacity()); }
1398QString &QString::setNum(short n, int base)
1399{ return setNum(qlonglong(n), base); }
1400QString &QString::setNum(ushort n, int base)
1401{ return setNum(qulonglong(n), base); }
1402QString &QString::setNum(int n, int base)
1403{ return setNum(qlonglong(n), base); }
1404QString &QString::setNum(uint n, int base)
1405{ return setNum(qulonglong(n), base); }
1406QString &QString::setNum(long n, int base)
1407{ return setNum(qlonglong(n), base); }
1408QString &QString::setNum(ulong n, int base)
1409{ return setNum(qulonglong(n), base); }
1410QString &QString::setNum(float n, char f, int prec)
1411{ return setNum(double(n),f,prec); }
1412#if QT_CORE_REMOVED_SINCE(6, 9)
1413QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const
1414{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
1415QString QString::arg(uint a, int fieldWidth, int base, QChar fillChar) const
1416{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
1417QString QString::arg(long a, int fieldWidth, int base, QChar fillChar) const
1418{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
1419QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const
1420{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
1421QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) const
1422{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
1423QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const
1424{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
1425#endif // QT_CORE_REMOVED_SINCE
1426
1427QString QString::section(QChar asep, qsizetype astart, qsizetype aend, SectionFlags aflags) const
1428{ return section(QString(asep), astart, aend, aflags); }
1429
1430QT_WARNING_PUSH
1431QT_WARNING_DISABLE_MSVC(4127) // "conditional expression is constant"
1432QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable"
1433
1434qsizetype QString::toWCharArray(wchar_t *array) const
1435{
1436 return qToStringViewIgnoringNull(*this).toWCharArray(array);
1437}
1438
1439qsizetype QStringView::toWCharArray(wchar_t *array) const
1440{
1441 if (sizeof(wchar_t) == sizeof(QChar)) {
1442 if (auto src = data())
1443 memcpy(array, src, sizeof(QChar) * size());
1444 return size();
1445 } else {
1446 return QString::toUcs4_helper(utf16(), size(), reinterpret_cast<char32_t *>(array));
1447 }
1448}
1449
1451
1452QString QString::fromWCharArray(const wchar_t *string, qsizetype size)
1453{
1454 if constexpr (sizeof(wchar_t) == sizeof(QChar)) {
1455 return QString(reinterpret_cast<const QChar *>(string), size);
1456 } else {
1457#ifdef QT_BOOTSTRAPPED
1458 Q_UNREACHABLE_RETURN(QString());
1459#else
1460 return fromUcs4(reinterpret_cast<const char32_t *>(string), size);
1461#endif
1462 }
1463}
1464
1465constexpr QString::QString() noexcept {}
1466QString::~QString() {}
1467
1468void QString::reserve(qsizetype asize)
1469{
1470 if (d.needsDetach() || asize >= capacity() - d.freeSpaceAtBegin())
1471 reallocData(qMax(asize, size()), QArrayData::KeepSize);
1472 if (d.constAllocatedCapacity())
1473 d.setFlag(Data::CapacityReserved);
1474}
1475
1476void QString::squeeze()
1477{
1478 if (!d.isMutable())
1479 return;
1480 if (d.needsDetach() || size() < capacity())
1481 reallocData(d.size, QArrayData::KeepSize);
1482 if (d.constAllocatedCapacity())
1483 d.clearFlag(Data::CapacityReserved);
1484}
1485
1486QChar &QString::operator[](qsizetype i)
1487{ verify(i, 1); return data()[i]; }
1488QChar &QString::front() { return operator[](0); }
1489QChar &QString::back() { return operator[](size() - 1); }
1490QString::iterator QString::begin()
1491{ detach(); return reinterpret_cast<QChar*>(d.data()); }
1492QString::const_iterator QString::begin() const
1493{ return reinterpret_cast<const QChar*>(d.data()); }
1494QString::const_iterator QString::cbegin() const
1495{ return reinterpret_cast<const QChar*>(d.data()); }
1496QString::const_iterator QString::constBegin() const
1497{ return reinterpret_cast<const QChar*>(d.data()); }
1498QString::iterator QString::end()
1499{ detach(); return reinterpret_cast<QChar*>(d.data() + d.size); }
1500QString::const_iterator QString::end() const
1501{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
1502QString::const_iterator QString::cend() const
1503{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
1504QString::const_iterator QString::constEnd() const
1505{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
1506bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
1507{ return indexOf(s, 0, cs) != -1; }
1508bool QString::contains(QLatin1StringView s, Qt::CaseSensitivity cs) const
1509{ return indexOf(s, 0, cs) != -1; }
1510bool QString::contains(QChar c, Qt::CaseSensitivity cs) const
1511{ return indexOf(c, 0, cs) != -1; }
1512bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
1513{ return indexOf(s, 0, cs) != -1; }
1514
1515#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1516#if QT_CORE_REMOVED_SINCE(6, 8)
1517bool QString::operator==(const char *s) const
1518{ return QString::compare_helper(constData(), size(), s, -1) == 0; }
1519bool QString::operator!=(const char *s) const
1520{ return QString::compare_helper(constData(), size(), s, -1) != 0; }
1521bool QString::operator<(const char *s) const
1522{ return QString::compare_helper(constData(), size(), s, -1) < 0; }
1523bool QString::operator>(const char *s) const
1524{ return QString::compare_helper(constData(), size(), s, -1) > 0; }
1525bool QString::operator<=(const char *s) const
1526{ return QString::compare_helper(constData(), size(), s, -1) <= 0; }
1527bool QString::operator>=(const char *s) const
1528{ return QString::compare_helper(constData(), size(), s, -1) >= 0; }
1529
1530QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const
1531{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) == 0; }
1532QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const
1533{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) != 0; }
1534QT_ASCII_CAST_WARN bool QString::operator<(const QByteArray &s) const
1535{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) < 0; }
1536QT_ASCII_CAST_WARN bool QString::operator>(const QByteArray &s) const
1537{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) > 0; }
1538QT_ASCII_CAST_WARN bool QString::operator<=(const QByteArray &s) const
1539{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) <= 0; }
1540QT_ASCII_CAST_WARN bool QString::operator>=(const QByteArray &s) const
1541{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) >= 0; }
1542
1543bool QByteArray::operator==(const QString &s) const
1544{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) == 0; }
1545bool QByteArray::operator!=(const QString &s) const
1546{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; }
1547bool QByteArray::operator<(const QString &s) const
1548{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; }
1549bool QByteArray::operator>(const QString &s) const
1550{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; }
1551bool QByteArray::operator<=(const QString &s) const
1552{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; }
1553bool QByteArray::operator>=(const QString &s) const
1554{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; }
1555#endif // QT_CORE_REMOVED_SINCE(6, 8)
1556#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1557
1558#if !defined(QT_USE_FAST_OPERATOR_PLUS) && !defined(QT_USE_QSTRINGBUILDER)
1559// QString + QString
1560inline QString operator+(const QString &s1, const QString &s2)
1561{ QString t(s1); t += s2; return t; }
1562inline QString operator+(QString &&lhs, const QString &rhs)
1563{ return std::move(lhs += rhs); }
1564inline QString operator+(const QString &s1, QChar s2)
1565{ QString t(s1); t += s2; return t; }
1566inline QString operator+(QString &&lhs, QChar rhs)
1567{ return std::move(lhs += rhs); }
1568inline QString operator+(QChar s1, const QString &s2)
1569{ QString t(s1); t += s2; return t; }
1570inline QString operator+(const QString &lhs, QStringView rhs)
1571{
1572 QString ret{lhs.size() + rhs.size(), Qt::Uninitialized};
1573 return ret.assign(lhs).append(rhs);
1574}
1575inline QString operator+(QStringView lhs, const QString &rhs)
1576{
1577 QString ret{lhs.size() + rhs.size(), Qt::Uninitialized};
1578 return ret.assign(lhs).append(rhs);
1579}
1580
1581# if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1582QT_ASCII_CAST_WARN inline QString operator+(const QString &s1, const char *s2)
1583{ QString t(s1); t += QUtf8StringView(s2); return t; }
1584QT_ASCII_CAST_WARN inline QString operator+(QString &&lhs, const char *rhs)
1585{ QT_IGNORE_DEPRECATIONS(return std::move(lhs += rhs);) }
1586QT_ASCII_CAST_WARN inline QString operator+(const char *s1, const QString &s2)
1587{ QString t = QString::fromUtf8(s1); t += s2; return t; }
1588QT_ASCII_CAST_WARN inline QString operator+(const QByteArray &ba, const QString &s)
1589{ QString t = QString::fromUtf8(ba); t += s; return t; }
1590QT_ASCII_CAST_WARN inline QString operator+(const QString &s, const QByteArray &ba)
1591{ QString t(s); t += QUtf8StringView(ba); return t; }
1592QT_ASCII_CAST_WARN inline QString operator+(QString &&lhs, const QByteArray &rhs)
1593{ QT_IGNORE_DEPRECATIONS(return std::move(lhs += rhs);) }
1594# endif // QT_NO_CAST_FROM_ASCII
1595#endif // QT_USE_QSTRINGBUILDER
1596
1597QString QString::fromStdString(const std::string &s)
1598{ return fromUtf8(s.data(), qsizetype(s.size())); }
1599
1600std::wstring QString::toStdWString() const
1601{
1602 std::wstring str;
1603 str.resize(size());
1604 str.resize(toWCharArray(str.data()));
1605 return str;
1606}
1607
1608QString QString::fromStdWString(const std::wstring &s)
1609{ return fromWCharArray(s.data(), qsizetype(s.size())); }
1610
1611QString QString::fromStdU16String(const std::u16string &s)
1612{ return fromUtf16(s.data(), qsizetype(s.size())); }
1613
1614std::u16string QString::toStdU16String() const
1615{ return std::u16string(reinterpret_cast<const char16_t*>(data()), size()); }
1616
1617QString QString::fromStdU32String(const std::u32string &s)
1618{ return fromUcs4(s.data(), qsizetype(s.size())); }
1619
1620std::u32string QString::toStdU32String() const
1621{
1622 std::u32string u32str(size(), char32_t(0));
1623 const qsizetype len = toUcs4_helper(reinterpret_cast<const char16_t *>(data()),
1624 size(), u32str.data());
1625 u32str.resize(len);
1626 return u32str;
1627}
1628
1629QString::operator std::u16string_view() const noexcept
1630{
1631 return std::u16string_view(d.data(), size_t(d.size));
1632}
1633
1634#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
1635Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QString &);
1636Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &);
1637#endif
1638
1640Q_DECLARE_OPERATORS_FOR_FLAGS(QString::SectionFlags)
1641
1642int QString::compare(QStringView s, Qt::CaseSensitivity cs) const noexcept
1643{ return -s.compare(*this, cs); }
1644
1645int QString::localeAwareCompare(QStringView s) const
1646{ return localeAwareCompare_helper(constData(), size(), s.constData(), s.size()); }
1647int QString::localeAwareCompare(QStringView s1, QStringView s2)
1648{ return localeAwareCompare_helper(s1.constData(), s1.size(), s2.constData(), s2.size()); }
1649int QStringView::localeAwareCompare(QStringView other) const
1650{ return QString::localeAwareCompare(*this, other); }
1651
1652#if QT_CORE_INLINE_IMPL_SINCE(6, 5)
1653qint64 QString::toLongLong(bool *ok, int base) const
1654{
1655 return toIntegral_helper<qlonglong>(*this, ok, base);
1656}
1657
1658quint64 QString::toULongLong(bool *ok, int base) const
1659{
1660 return toIntegral_helper<qulonglong>(*this, ok, base);
1661}
1662#endif
1663#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
1664qsizetype QString::indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
1665{
1666 return qToStringViewIgnoringNull(*this).indexOf(ch, from, cs);
1667}
1668qsizetype QString::lastIndexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
1669{
1670 return qToStringViewIgnoringNull(*this).lastIndexOf(ch, from, cs);
1671}
1672#endif
1673#if QT_CORE_INLINE_IMPL_SINCE(6, 10)
1674QString QString::fromRawData(const QChar *unicode, qsizetype size)
1675{
1676 return fromRawData(reinterpret_cast<const char16_t *>(unicode), size);
1677}
1678#endif
1679#if QT_CORE_INLINE_IMPL_SINCE(6, 12)
1680qsizetype QString::indexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
1681{
1682 return indexOf(QStringView(str.begin(), str.size()), from, cs);
1683}
1684qsizetype QString::indexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
1685{
1686 return QStringView(begin(), size()).indexOf(str, from, cs);
1687}
1688qsizetype QString::lastIndexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
1689{
1690 return lastIndexOf(QStringView(str.begin(), str.size()), from, cs);
1691}
1692qsizetype QString::lastIndexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
1693{
1694 return QStringView(begin(), size()).lastIndexOf(str, from, cs);
1695}
1696#endif
1697
1698namespace QtPrivate {
1699// used by qPrintable() and qUtf8Printable() macros
1700inline const QString &asString(const QString &s) { return s; }
1701inline QString &&asString(QString &&s) { return std::move(s); }
1702}
1703
1704#ifndef qPrintable
1705# define qPrintable(string) QtPrivate::asString(string).toLocal8Bit().constData()
1706#endif
1707
1708#ifndef qUtf8Printable
1709# define qUtf8Printable(string) QtPrivate::asString(string).toUtf8().constData()
1710#endif
1711
1712/*
1713 Wrap QString::constData() with enough casts to allow passing it
1714 to QString::asprintf("%ls") without warnings.
1715*/
1716#ifndef qUtf16Printable
1717# define qUtf16Printable(string)
1718 static_cast<const wchar_t *>(
1719 static_cast<const void *>(QtPrivate::asString(string).nullTerminated().constData()))
1720#endif
1721
1722//
1723// QStringView::arg() implementation
1724//
1725
1726namespace QtPrivate {
1727
1728struct ArgBase {
1729 enum Tag : uchar { L1, Any, U16 } tag;
1730};
1731
1734 QStringViewArg() = default;
1735 constexpr explicit QStringViewArg(QStringView v) noexcept : ArgBase{U16}, string{v} {}
1736};
1737
1740 QLatin1StringArg() = default;
1741 constexpr explicit QLatin1StringArg(QLatin1StringView v) noexcept : ArgBase{L1}, string{v} {}
1742};
1743
1746 QAnyStringArg() = default;
1747 constexpr explicit QAnyStringArg(QAnyStringView v) noexcept : ArgBase{Any}, string{v} {}
1748};
1749
1750#if QT_CORE_REMOVED_SINCE(6, 9)
1753#endif
1754[[nodiscard]] Q_CORE_EXPORT QString argToQString(QAnyStringView pattern, size_t n, const ArgBase **args);
1755
1756template <typename...Args>
1757[[nodiscard]] Q_ALWAYS_INLINE QString argToQStringDispatch(QAnyStringView pattern, const Args &...args)
1758{
1759 const ArgBase *argBases[] = {&args..., /* avoid zero-sized array */ nullptr};
1760 return QtPrivate::argToQString(pattern, sizeof...(Args), argBases);
1761}
1762
1763constexpr inline QAnyStringArg qStringLikeToArg(QAnyStringView s) noexcept { return QAnyStringArg{s}; }
1764
1765} // namespace QtPrivate
1766
1767template <typename...Args>
1769QString QStringView::arg(Args &&...args) const
1770{
1771 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1772}
1773
1774template <typename...Args>
1776QString QLatin1StringView::arg(Args &&...args) const
1777{
1778 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1779}
1780
1781template <bool HasChar8T>
1782template <typename...Args>
1783QString QBasicUtf8StringView<HasChar8T>::arg(Args &&...args) const
1784{
1785 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1786}
1787
1788template <typename...Args>
1789QString QAnyStringView::arg(Args &&...args) const
1790{
1791 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1792}
1793
1794template <typename T>
1795qsizetype erase(QString &s, const T &t)
1796{
1797 return s.removeIf_helper([&t](const auto &e) { return t == e; });
1798}
1799
1800template <typename Predicate>
1801qsizetype erase_if(QString &s, Predicate pred)
1802{
1803 return s.removeIf_helper(pred);
1804}
1805
1806namespace Qt {
1807inline namespace Literals {
1808inline namespace StringLiterals {
1809inline QString operator""_s(const char16_t *str, size_t size) noexcept
1810{
1811 return QString(QStringPrivate(nullptr, const_cast<char16_t *>(str), qsizetype(size)));
1812}
1813
1814} // StringLiterals
1815} // Literals
1816} // Qt
1817
1818inline namespace QtLiterals {
1819#if QT_DEPRECATED_SINCE(6, 8)
1820
1821QT_DEPRECATED_VERSION_X_6_8("Use _s from Qt::StringLiterals namespace instead.")
1822inline QString operator""_qs(const char16_t *str, size_t size) noexcept
1823{
1824 return Qt::StringLiterals::operator""_s(str, size);
1825}
1826
1827#endif // QT_DEPRECATED_SINCE(6, 8)
1828} // QtLiterals
1829
1830// all our supported compilers support Unicode string literals,
1831// even if their Q_COMPILER_UNICODE_STRING has been revoked due
1832// to lacking stdlib support. But QStringLiteral only needs the
1833// core language feature, so just use u"" here unconditionally:
1834
1835#define QT_UNICODE_LITERAL(str) u"" str
1836
1837namespace QtPrivate {
1838template <qsizetype N>
1839Q_ALWAYS_INLINE static QStringPrivate qMakeStringPrivate(const char16_t (&literal)[N])
1840{
1841 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1842 auto str = const_cast<char16_t *>(literal);
1843 return { nullptr, str, N - 1 };
1844}
1845} // namespace QtPrivate
1846
1847#define QStringLiteral(str) (QString(QtPrivate::qMakeStringPrivate(QT_UNICODE_LITERAL(str)))) /**/
1848
1849QT_END_NAMESPACE
1850
1851#include <QtCore/qstringbuilder.h>
1852#include <QtCore/qstringconverter.h>
1853
1854#ifdef Q_L1S_VIEW_IS_PRIMARY
1855# undef Q_L1S_VIEW_IS_PRIMARY
1856#endif
1857
1858#endif // QSTRING_H
\inmodule QtCore\reentrant
Definition qdatastream.h:50
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:177
QString && asString(QString &&s)
Definition qstring.h:1701
constexpr QAnyStringArg qStringLikeToArg(QAnyStringView s) noexcept
Definition qstring.h:1763
const QString & asString(const QString &s)
Definition qstring.h:1700
std::is_same< Char, char32_t > IsCompatibleChar32TypeHelper
Definition qstring.h:57
constexpr bool isLatin1(QLatin1StringView s) noexcept
Definition qstring.h:77
QString operator""_s(const char16_t *str, size_t size) noexcept
Definition qstring.h:1809
Definition qcompare.h:111
#define __has_builtin(x)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n)
\inmodule QtCore \title Global Qt Declarations
Definition qglobal.cpp:100
QString operator+(const QString &s1, QChar s2)
Definition qstring.h:1564
QString operator+(QString &&lhs, const QString &rhs)
Definition qstring.h:1562
qsizetype erase_if(QString &s, Predicate pred)
Definition qstring.h:1801
#define QT_UNICODE_LITERAL(str)
Definition qstring.h:1835
QString operator+(QString &&lhs, QChar rhs)
Definition qstring.h:1566
QString operator+(QChar s1, const QString &s2)
Definition qstring.h:1568
QString operator+(const QString &s1, const QString &s2)
Definition qstring.h:1560
qsizetype erase(QString &s, const T &t)
Definition qstring.h:1795
QList< QList< qInternalCallback > > callbacks
Definition qglobal.cpp:129
constexpr QAnyStringArg(QAnyStringView v) noexcept
Definition qstring.h:1747
QAnyStringView string
Definition qstring.h:1745
QLatin1StringView string
Definition qstring.h:1739
constexpr QLatin1StringArg(QLatin1StringView v) noexcept
Definition qstring.h:1741
constexpr QStringViewArg(QStringView v) noexcept
Definition qstring.h:1735