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

source code of qtbase/src/corelib/text/qstring.h