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]] qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
409 [[nodiscard]] qsizetype indexOf(const QString &s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
410 [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
411 { return QtPrivate::findString(*this, from, s, cs); }
412 [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
413 { return lastIndexOf(c, -1, cs); }
414 [[nodiscard]] QT_CORE_INLINE_SINCE(6, 8)
415 qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
416 [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
417 { return lastIndexOf(s, size(), cs); }
418 [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
419 [[nodiscard]] qsizetype lastIndexOf(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
420 { return lastIndexOf(s, size(), cs); }
421 [[nodiscard]] qsizetype lastIndexOf(const QString &s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
422
423 [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
424 { return lastIndexOf(s, size(), cs); }
425 [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
426 { return QtPrivate::lastIndexOf(*this, from, s, cs); }
427
428 [[nodiscard]] inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
429 [[nodiscard]] inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
430 [[nodiscard]] inline bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
431 [[nodiscard]] inline bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
432 [[nodiscard]] qsizetype count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
433 [[nodiscard]] qsizetype count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
434 [[nodiscard]] qsizetype count(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
435
436#if QT_CONFIG(regularexpression)
437 [[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0,
438 QRegularExpressionMatch *rmatch = nullptr) const;
439#ifdef Q_QDOC
440 [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
441#else
442 // prevent an ambiguity when called like this: lastIndexOf(re, 0)
443 template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false>
444 [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, T *rmatch = nullptr) const
445 { return lastIndexOf(re, size(), rmatch); }
446#endif
447 [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from,
448 QRegularExpressionMatch *rmatch = nullptr) const;
449 [[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
450 [[nodiscard]] qsizetype count(const QRegularExpression &re) const;
451#endif
452
453 enum SectionFlag {
454 SectionDefault = 0x00,
455 SectionSkipEmpty = 0x01,
456 SectionIncludeLeadingSep = 0x02,
457 SectionIncludeTrailingSep = 0x04,
458 SectionCaseInsensitiveSeps = 0x08
459 };
460 Q_DECLARE_FLAGS(SectionFlags, SectionFlag)
461
462 [[nodiscard]] inline QString section(QChar sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
463 [[nodiscard]] QString section(const QString &in_sep, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
464#if QT_CONFIG(regularexpression)
465 [[nodiscard]] QString section(const QRegularExpression &re, qsizetype start, qsizetype end = -1, SectionFlags flags = SectionDefault) const;
466#endif
467
468#if QT_CORE_REMOVED_SINCE(6, 7)
469 QString left(qsizetype n) const;
470 QString right(qsizetype n) const;
471 QString mid(qsizetype position, qsizetype n = -1) const;
472
473 QString first(qsizetype n) const;
474 QString last(qsizetype n) const;
475 QString sliced(qsizetype pos) const;
476 QString sliced(qsizetype pos, qsizetype n) const;
477 QString chopped(qsizetype n) const;
478#else
479 [[nodiscard]] QString left(qsizetype n) const &
480 {
481 if (size_t(n) >= size_t(size()))
482 return *this;
483 return first(n);
484 }
485 [[nodiscard]] QString left(qsizetype n) &&
486 {
487 if (size_t(n) >= size_t(size()))
488 return std::move(*this);
489 return std::move(*this).first(n);
490 }
491 [[nodiscard]] QString right(qsizetype n) const &
492 {
493 if (size_t(n) >= size_t(size()))
494 return *this;
495 return last(n);
496 }
497 [[nodiscard]] QString right(qsizetype n) &&
498 {
499 if (size_t(n) >= size_t(size()))
500 return std::move(*this);
501 return std::move(*this).last(n);
502 }
503 [[nodiscard]] QString mid(qsizetype position, qsizetype n = -1) const &;
504 [[nodiscard]] QString mid(qsizetype position, qsizetype n = -1) &&;
505
506 [[nodiscard]] QString first(qsizetype n) const &
507 { verify(0, n); return sliced(0, n); }
508 [[nodiscard]] QString last(qsizetype n) const &
509 { verify(0, n); return sliced(size() - n, n); }
510 [[nodiscard]] QString sliced(qsizetype pos) const &
511 { verify(pos, 0); return sliced(pos, size() - pos); }
512 [[nodiscard]] QString sliced(qsizetype pos, qsizetype n) const &
513 { verify(pos, n); return QString(begin() + pos, n); }
514 [[nodiscard]] QString chopped(qsizetype n) const &
515 { verify(0, n); return sliced(0, size() - n); }
516
517 [[nodiscard]] QString first(qsizetype n) &&
518 {
519 verify(0, n);
520 resize(n); // may detach and allocate memory
521 return std::move(*this);
522 }
523 [[nodiscard]] QString last(qsizetype n) &&
524 { verify(0, n); return sliced_helper(*this, size() - n, n); }
525 [[nodiscard]] QString sliced(qsizetype pos) &&
526 { verify(pos, 0); return sliced_helper(*this, pos, size() - pos); }
527 [[nodiscard]] QString sliced(qsizetype pos, qsizetype n) &&
528 { verify(pos, n); return sliced_helper(*this, pos, n); }
529 [[nodiscard]] QString chopped(qsizetype n) &&
530 { verify(0, n); return std::move(*this).first(size() - n); }
531#endif
532 bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
533 [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
534 { return QtPrivate::startsWith(*this, s, cs); }
535 bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
536 bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
537
538 bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
539 [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
540 { return QtPrivate::endsWith(*this, s, cs); }
541 bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
542 bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
543
544 bool isUpper() const;
545 bool isLower() const;
546
547 [[nodiscard]] QString leftJustified(qsizetype width, QChar fill = u' ', bool trunc = false) const;
548 [[nodiscard]] QString rightJustified(qsizetype width, QChar fill = u' ', bool trunc = false) const;
549
550#if !defined(Q_QDOC)
551 [[nodiscard]] QString toLower() const &
552 { return toLower_helper(*this); }
553 [[nodiscard]] QString toLower() &&
554 { return toLower_helper(*this); }
555 [[nodiscard]] QString toUpper() const &
556 { return toUpper_helper(*this); }
557 [[nodiscard]] QString toUpper() &&
558 { return toUpper_helper(*this); }
559 [[nodiscard]] QString toCaseFolded() const &
560 { return toCaseFolded_helper(*this); }
561 [[nodiscard]] QString toCaseFolded() &&
562 { return toCaseFolded_helper(*this); }
563 [[nodiscard]] QString trimmed() const &
564 { return trimmed_helper(*this); }
565 [[nodiscard]] QString trimmed() &&
566 { return trimmed_helper(*this); }
567 [[nodiscard]] QString simplified() const &
568 { return simplified_helper(*this); }
569 [[nodiscard]] QString simplified() &&
570 { return simplified_helper(*this); }
571#else
572 [[nodiscard]] QString toLower() const;
573 [[nodiscard]] QString toUpper() const;
574 [[nodiscard]] QString toCaseFolded() const;
575 [[nodiscard]] QString trimmed() const;
576 [[nodiscard]] QString simplified() const;
577#endif
578 [[nodiscard]] QString toHtmlEscaped() const;
579
580 QString &insert(qsizetype i, QChar c);
581 QString &insert(qsizetype i, const QChar *uc, qsizetype len);
582 inline QString &insert(qsizetype i, const QString &s) { return insert(i, s.constData(), s.size()); }
583 inline QString &insert(qsizetype i, QStringView v) { return insert(i, v.data(), v.size()); }
584 QString &insert(qsizetype i, QLatin1StringView s);
585 QString &insert(qsizetype i, QUtf8StringView s);
586
587 QString &append(QChar c);
588 QString &append(const QChar *uc, qsizetype len);
589 QString &append(const QString &s);
590 inline QString &append(QStringView v) { return append(v.data(), v.size()); }
591 QString &append(QLatin1StringView s);
592 QString &append(QUtf8StringView s);
593
594 inline QString &prepend(QChar c) { return insert(0, c); }
595 inline QString &prepend(const QChar *uc, qsizetype len) { return insert(0, uc, len); }
596 inline QString &prepend(const QString &s) { return insert(0, s); }
597 inline QString &prepend(QStringView v) { return prepend(v.data(), v.size()); }
598 inline QString &prepend(QLatin1StringView s) { return insert(0, s); }
599 QString &prepend(QUtf8StringView s) { return insert(0, s); }
600
601 QString &assign(QAnyStringView s);
602 inline QString &assign(qsizetype n, QChar c)
603 {
604 Q_ASSERT(n >= 0);
605 return fill(c, n);
606 }
607 template <typename InputIterator, if_compatible_iterator<InputIterator> = true>
608 QString &assign(InputIterator first, InputIterator last)
609 {
610 using V = typename std::iterator_traits<InputIterator>::value_type;
611 constexpr bool IsL1C = std::is_same_v<std::remove_cv_t<V>, QLatin1Char>;
612 constexpr bool IsFwdIt = std::is_convertible_v<
613 typename std::iterator_traits<InputIterator>::iterator_category,
614 std::forward_iterator_tag
615 >;
616
617 if constexpr (is_contiguous_iterator_v<InputIterator>) {
618 const auto p = q20::to_address(first);
619 const auto len = qsizetype(last - first);
620 if constexpr (IsL1C)
621 return assign(QLatin1StringView(reinterpret_cast<const char*>(p), len));
622 else if constexpr (sizeof(V) == 4)
623 return assign_helper(p, len);
624 else
625 return assign(QAnyStringView(p, len));
626 } else if constexpr (sizeof(V) == 4) { // non-contiguous iterator, feed data piecemeal
627 resize(0);
628 if constexpr (IsFwdIt) {
629 const qsizetype requiredCapacity = 2 * std::distance(first, last);
630 reserve(requiredCapacity);
631 }
632 while (first != last) {
633 append(QChar::fromUcs4(*first));
634 ++first;
635 }
636 return *this;
637 } else if constexpr (QtPrivate::IsCompatibleChar8Type<V>::value) {
638 assign_helper_char8(first, last);
639 if (d.constAllocatedCapacity())
640 d.data()[d.size] = u'\0';
641 return *this;
642 } else {
643 d->assign(first, last, [](QChar ch) -> char16_t { return ch.unicode(); });
644 if (d.constAllocatedCapacity())
645 d.data()[d.size] = u'\0';
646 return *this;
647 }
648 }
649
650 inline QString &operator+=(QChar c) { return append(c); }
651
652 inline QString &operator+=(const QString &s) { return append(s); }
653 inline QString &operator+=(QStringView v) { return append(v); }
654 inline QString &operator+=(QLatin1StringView s) { return append(s); }
655 QString &operator+=(QUtf8StringView s) { return append(s); }
656
657#if defined(QT_RESTRICTED_CAST_FROM_ASCII)
658 template <qsizetype N>
659 QString &insert(qsizetype i, const char (&ch)[N]) { return insert(i, QUtf8StringView(ch)); }
660 template <qsizetype N>
661 QString &append(const char (&ch)[N]) { return append(QUtf8StringView(ch)); }
662 template <qsizetype N>
663 QString &prepend(const char (&ch)[N]) { return prepend(QUtf8StringView(ch)); }
664 template <qsizetype N>
665 QString &operator+=(const char (&ch)[N]) { return append(QUtf8StringView(ch)); }
666#endif
667
668 QString &remove(qsizetype i, qsizetype len);
669 QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive);
670 QString &remove(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
671 QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
672
673 QString &removeAt(qsizetype pos)
674 { return size_t(pos) < size_t(size()) ? remove(pos, 1) : *this; }
675 QString &removeFirst() { return !isEmpty() ? remove(0, 1) : *this; }
676 QString &removeLast() { return !isEmpty() ? remove(size() - 1, 1) : *this; }
677
678 template <typename Predicate>
679 QString &removeIf(Predicate pred)
680 {
681 removeIf_helper(pred);
682 return *this;
683 }
684
685 QString &replace(qsizetype i, qsizetype len, QChar after);
686 QString &replace(qsizetype i, qsizetype len, const QChar *s, qsizetype slen);
687 QString &replace(qsizetype i, qsizetype len, const QString &after);
688 QString &replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
689 QString &replace(const QChar *before, qsizetype blen, const QChar *after, qsizetype alen, Qt::CaseSensitivity cs = Qt::CaseSensitive);
690 QString &replace(QLatin1StringView before, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
691 QString &replace(QLatin1StringView before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
692 QString &replace(const QString &before, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
693 QString &replace(const QString &before, const QString &after,
694 Qt::CaseSensitivity cs = Qt::CaseSensitive);
695 QString &replace(QChar c, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
696 QString &replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
697#if QT_CONFIG(regularexpression)
698 QString &replace(const QRegularExpression &re, const QString &after);
699 inline QString &remove(const QRegularExpression &re)
700 { return replace(re, QString()); }
701#endif
702
703public:
704 [[nodiscard]]
705 QStringList split(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
706 Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
707 [[nodiscard]]
708 QStringList split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts,
709 Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
710#ifndef QT_NO_REGULAREXPRESSION
711 [[nodiscard]]
712 QStringList split(const QRegularExpression &sep,
713 Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
714#endif
715
716 template <typename Needle, typename...Flags>
717 [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) const &
718 noexcept(noexcept(qTokenize(std::declval<const QString &>(), std::forward<Needle>(needle), flags...)))
719 -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
720 { return qTokenize(qToStringViewIgnoringNull(*this), std::forward<Needle>(needle), flags...); }
721
722 template <typename Needle, typename...Flags>
723 [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) const &&
724 noexcept(noexcept(qTokenize(std::declval<const QString>(), std::forward<Needle>(needle), flags...)))
725 -> decltype(qTokenize(std::move(*this), std::forward<Needle>(needle), flags...))
726 { return qTokenize(std::move(*this), std::forward<Needle>(needle), flags...); }
727
728 template <typename Needle, typename...Flags>
729 [[nodiscard]] inline auto tokenize(Needle &&needle, Flags...flags) &&
730 noexcept(noexcept(qTokenize(std::declval<QString>(), std::forward<Needle>(needle), flags...)))
731 -> decltype(qTokenize(std::move(*this), std::forward<Needle>(needle), flags...))
732 { return qTokenize(std::move(*this), std::forward<Needle>(needle), flags...); }
733
734
735 enum NormalizationForm {
736 NormalizationForm_D,
737 NormalizationForm_C,
738 NormalizationForm_KD,
739 NormalizationForm_KC
740 };
741 [[nodiscard]] QString normalized(NormalizationForm mode, QChar::UnicodeVersion version = QChar::Unicode_Unassigned) const;
742
743 [[nodiscard]] QString repeated(qsizetype times) const;
744
745 const ushort *utf16() const; // ### Qt 7 char16_t
746 [[nodiscard]] QString nullTerminated() const &;
747 [[nodiscard]] QString nullTerminated() &&;
748 QString &nullTerminate();
749
750#if !defined(Q_QDOC)
751 [[nodiscard]] QByteArray toLatin1() const &
752 { return toLatin1_helper(*this); }
753 [[nodiscard]] QByteArray toLatin1() &&
754 { return toLatin1_helper_inplace(*this); }
755 [[nodiscard]] QByteArray toUtf8() const &
756 { return toUtf8_helper(*this); }
757 [[nodiscard]] QByteArray toUtf8() &&
758 { return toUtf8_helper(*this); }
759 [[nodiscard]] QByteArray toLocal8Bit() const &
760 { return toLocal8Bit_helper(isNull() ? nullptr : constData(), size()); }
761 [[nodiscard]] QByteArray toLocal8Bit() &&
762 { return toLocal8Bit_helper(isNull() ? nullptr : constData(), size()); }
763#else
764 [[nodiscard]] QByteArray toLatin1() const;
765 [[nodiscard]] QByteArray toUtf8() const;
766 [[nodiscard]] QByteArray toLocal8Bit() const;
767#endif
768 [[nodiscard]] QList<uint> toUcs4() const; // ### Qt 7 char32_t
769
770 // note - this are all inline so we can benefit from strlen() compile time optimizations
771 static QString fromLatin1(QByteArrayView ba);
772 Q_WEAK_OVERLOAD
773 static inline QString fromLatin1(const QByteArray &ba) { return fromLatin1(QByteArrayView(ba)); }
774 static inline QString fromLatin1(const char *str, qsizetype size)
775 {
776 return fromLatin1(QByteArrayView(str, !str || size < 0 ? qstrlen(str) : size));
777 }
778 static QString fromUtf8(QByteArrayView utf8);
779 Q_WEAK_OVERLOAD
780 static inline QString fromUtf8(const QByteArray &ba) { return fromUtf8(QByteArrayView(ba)); }
781 static inline QString fromUtf8(const char *utf8, qsizetype size)
782 {
783 return fromUtf8(QByteArrayView(utf8, !utf8 || size < 0 ? qstrlen(utf8) : size));
784 }
785#if defined(__cpp_char8_t) || defined(Q_QDOC)
786 Q_WEAK_OVERLOAD
787 static inline QString fromUtf8(const char8_t *str)
788 { return fromUtf8(reinterpret_cast<const char *>(str)); }
789 Q_WEAK_OVERLOAD
790 static inline QString fromUtf8(const char8_t *str, qsizetype size)
791 { return fromUtf8(reinterpret_cast<const char *>(str), size); }
792#endif
793 static QString fromLocal8Bit(QByteArrayView ba);
794 Q_WEAK_OVERLOAD
795 static inline QString fromLocal8Bit(const QByteArray &ba) { return fromLocal8Bit(QByteArrayView(ba)); }
796 static inline QString fromLocal8Bit(const char *str, qsizetype size)
797 {
798 return fromLocal8Bit(QByteArrayView(str, !str || size < 0 ? qstrlen(str) : size));
799 }
800 static QString fromUtf16(const char16_t *, qsizetype size = -1);
801 static QString fromUcs4(const char32_t *, qsizetype size = -1);
802 static QString fromRawData(const char16_t *unicode, qsizetype size)
803 {
804 return QString(DataPointer::fromRawData(unicode, size));
805 }
806 QT_CORE_INLINE_SINCE(6, 10)
807 static QString fromRawData(const QChar *, qsizetype size);
808
809#if QT_DEPRECATED_SINCE(6, 0)
810 QT_DEPRECATED_VERSION_X_6_0("Use char16_t* overload.")
811 static QString fromUtf16(const ushort *str, qsizetype size = -1)
812 { return fromUtf16(reinterpret_cast<const char16_t *>(str), size); }
813 QT_DEPRECATED_VERSION_X_6_0("Use char32_t* overload.")
814 static QString fromUcs4(const uint *str, qsizetype size = -1)
815 { return fromUcs4(reinterpret_cast<const char32_t *>(str), size); }
816#endif
817
818 inline qsizetype toWCharArray(wchar_t *array) const;
819 [[nodiscard]] static inline QString fromWCharArray(const wchar_t *string, qsizetype size = -1);
820
821 QString &setRawData(const QChar *unicode, qsizetype size);
822 QString &setUnicode(const QChar *unicode, qsizetype size);
823 Q_WEAK_OVERLOAD
824 QString &setUnicode(const char16_t *utf16, qsizetype size)
825 { return setUnicode(reinterpret_cast<const QChar *>(utf16), size); }
826 QString &setUtf16(const char16_t *utf16, qsizetype size)
827 { return setUnicode(reinterpret_cast<const QChar *>(utf16), size); }
828
829#if !QT_CORE_REMOVED_SINCE(6, 9)
830 Q_WEAK_OVERLOAD
831#endif
832 QString &setUtf16(const ushort *autf16, qsizetype asize)
833 { return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
834
835 int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
836 int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
837 inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
838 int compare(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
839 { return compare(QStringView{&ch, 1}, cs); }
840
841 static inline int compare(const QString &s1, const QString &s2,
842 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
843 { return s1.compare(s2, cs); }
844
845 static inline int compare(const QString &s1, QLatin1StringView s2,
846 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
847 { return s1.compare(s2, cs); }
848 static inline int compare(QLatin1StringView s1, const QString &s2,
849 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
850 { return -s2.compare(s1, cs); }
851 static int compare(const QString &s1, QStringView s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
852 { return s1.compare(s2, cs); }
853 static int compare(QStringView s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
854 { return -s2.compare(s1, cs); }
855
856 int localeAwareCompare(const QString& s) const;
857 inline int localeAwareCompare(QStringView s) const;
858 static int localeAwareCompare(const QString& s1, const QString& s2)
859 { return s1.localeAwareCompare(s2); }
860
861 static inline int localeAwareCompare(QStringView s1, QStringView s2);
862
863 short toShort(bool *ok=nullptr, int base=10) const
864 { return toIntegral_helper<short>(*this, ok, base); }
865 ushort toUShort(bool *ok=nullptr, int base=10) const
866 { return toIntegral_helper<ushort>(*this, ok, base); }
867 int toInt(bool *ok=nullptr, int base=10) const
868 { return toIntegral_helper<int>(*this, ok, base); }
869 uint toUInt(bool *ok=nullptr, int base=10) const
870 { return toIntegral_helper<uint>(*this, ok, base); }
871 long toLong(bool *ok=nullptr, int base=10) const
872 { return toIntegral_helper<long>(*this, ok, base); }
873 ulong toULong(bool *ok=nullptr, int base=10) const
874 { return toIntegral_helper<ulong>(*this, ok, base); }
875 QT_CORE_INLINE_SINCE(6, 5)
876 qlonglong toLongLong(bool *ok=nullptr, int base=10) const;
877 QT_CORE_INLINE_SINCE(6, 5)
878 qulonglong toULongLong(bool *ok=nullptr, int base=10) const;
879 float toFloat(bool *ok=nullptr) const;
880 double toDouble(bool *ok=nullptr) const;
881
882 inline QString &setNum(short, int base=10);
883 inline QString &setNum(ushort, int base=10);
884 inline QString &setNum(int, int base=10);
885 inline QString &setNum(uint, int base=10);
886 inline QString &setNum(long, int base=10);
887 inline QString &setNum(ulong, int base=10);
888 QString &setNum(qlonglong, int base=10);
889 QString &setNum(qulonglong, int base=10);
890 inline QString &setNum(float, char format='g', int precision=6);
891 QString &setNum(double, char format='g', int precision=6);
892
893 static QString number(int, int base=10);
894 static QString number(uint, int base=10);
895 static QString number(long, int base=10);
896 static QString number(ulong, int base=10);
897 static QString number(qlonglong, int base=10);
898 static QString number(qulonglong, int base=10);
899 static QString number(double, char format='g', int precision=6);
900
901 friend bool comparesEqual(const QString &s1, const QString &s2) noexcept
902 { return comparesEqual(QStringView(s1), QStringView(s2)); }
903 friend Qt::strong_ordering compareThreeWay(const QString &s1, const QString &s2) noexcept
904 { return compareThreeWay(QStringView(s1), QStringView(s2)); }
905 Q_DECLARE_STRONGLY_ORDERED(QString)
906
907 Q_WEAK_OVERLOAD
908 friend bool comparesEqual(const QString &s1, QUtf8StringView s2) noexcept
909 { return QtPrivate::equalStrings(s1, s2); }
910 Q_WEAK_OVERLOAD
911 friend Qt::strong_ordering compareThreeWay(const QString &s1, QUtf8StringView s2) noexcept
912 {
913 const int res = QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive);
914 return Qt::compareThreeWay(res, 0);
915 }
916 Q_DECLARE_STRONGLY_ORDERED(QString, QUtf8StringView, Q_WEAK_OVERLOAD)
917
918#ifdef __cpp_char8_t
919 friend bool comparesEqual(const QString &s1, const char8_t *s2) noexcept
920 { return comparesEqual(s1, QUtf8StringView(s2)); }
921 friend Qt::strong_ordering compareThreeWay(const QString &s1, const char8_t *s2) noexcept
922 { return compareThreeWay(s1, QUtf8StringView(s2)); }
923 Q_DECLARE_STRONGLY_ORDERED(QString, const char8_t *)
924#endif // __cpp_char8_t
925
926 friend bool comparesEqual(const QString &s1, QLatin1StringView s2) noexcept
927 { return (s1.size() == s2.size()) && QtPrivate::equalStrings(s1, s2); }
928 friend Qt::strong_ordering
929 compareThreeWay(const QString &s1, QLatin1StringView s2) noexcept
930 {
931 const int res = QtPrivate::compareStrings(s1, s2, Qt::CaseSensitive);
932 return Qt::compareThreeWay(res, 0);
933 }
934 Q_DECLARE_STRONGLY_ORDERED(QString, QLatin1StringView)
935
936 // Check isEmpty() instead of isNull() for backwards compatibility.
937 friend bool comparesEqual(const QString &s1, std::nullptr_t) noexcept
938 { return s1.isEmpty(); }
939 friend Qt::strong_ordering compareThreeWay(const QString &s1, std::nullptr_t) noexcept
940 { return s1.isEmpty() ? Qt::strong_ordering::equivalent : Qt::strong_ordering::greater; }
941 Q_DECLARE_STRONGLY_ORDERED(QString, std::nullptr_t)
942
943 friend bool comparesEqual(const QString &s1, const char16_t *s2) noexcept
944 { return comparesEqual(s1, QStringView(s2)); }
945 friend Qt::strong_ordering compareThreeWay(const QString &s1, const char16_t *s2) noexcept
946 { return compareThreeWay(s1, QStringView(s2)); }
947 Q_DECLARE_STRONGLY_ORDERED(QString, const char16_t *)
948
949 // QChar <> QString
950 friend bool comparesEqual(const QString &lhs, QChar rhs) noexcept
951 { return lhs.size() == 1 && rhs == lhs.front(); }
952 friend Qt::strong_ordering compareThreeWay(const QString &lhs, QChar rhs) noexcept
953 {
954 const int res = compare_helper(lhs.data(), lhs.size(), &rhs, 1);
955 return Qt::compareThreeWay(res, 0);
956 }
957 Q_DECLARE_STRONGLY_ORDERED(QString, QChar)
958
959 // ASCII compatibility
960#if defined(QT_RESTRICTED_CAST_FROM_ASCII)
961 template <qsizetype N>
962 inline QString(const char (&ch)[N])
963 : QString(fromUtf8(ch))
964 {}
965 template <qsizetype N>
966 QString(char (&)[N]) = delete;
967 template <qsizetype N>
968 inline QString &operator=(const char (&ch)[N])
969 { return (*this = fromUtf8(ch, N - 1)); }
970 template <qsizetype N>
971 QString &operator=(char (&)[N]) = delete;
972#endif
973#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
974 QT_ASCII_CAST_WARN inline QString(const char *ch)
975 : QString(fromUtf8(ch))
976 {}
977 QT_ASCII_CAST_WARN inline QString(const QByteArray &a)
978 : QString(fromUtf8(a))
979 {}
980 QT_ASCII_CAST_WARN inline QString &operator=(const char *ch)
981 {
982 if (!ch) {
983 clear();
984 return *this;
985 }
986 return assign(ch);
987 }
988 QT_ASCII_CAST_WARN inline QString &operator=(const QByteArray &a)
989 {
990 if (a.isNull()) {
991 clear();
992 return *this;
993 }
994 return assign(a);
995 }
996 // these are needed, so it compiles with STL support enabled
997 QT_ASCII_CAST_WARN inline QString &prepend(const char *s)
998 { return prepend(QUtf8StringView(s)); }
999 QT_ASCII_CAST_WARN inline QString &prepend(const QByteArray &s)
1000 { return prepend(QUtf8StringView(s)); }
1001 QT_ASCII_CAST_WARN inline QString &append(const char *s)
1002 { return append(QUtf8StringView(s)); }
1003 QT_ASCII_CAST_WARN inline QString &append(const QByteArray &s)
1004 { return append(QUtf8StringView(s)); }
1005 QT_ASCII_CAST_WARN inline QString &insert(qsizetype i, const char *s)
1006 { return insert(i, QUtf8StringView(s)); }
1007 QT_ASCII_CAST_WARN inline QString &insert(qsizetype i, const QByteArray &s)
1008 { return insert(i, QUtf8StringView(s)); }
1009 QT_ASCII_CAST_WARN inline QString &operator+=(const char *s)
1010 { return append(QUtf8StringView(s)); }
1011 QT_ASCII_CAST_WARN inline QString &operator+=(const QByteArray &s)
1012 { return append(QUtf8StringView(s)); }
1013
1014#if QT_CORE_REMOVED_SINCE(6, 8)
1015 QT_ASCII_CAST_WARN inline bool operator==(const char *s) const;
1016 QT_ASCII_CAST_WARN inline bool operator!=(const char *s) const;
1017 QT_ASCII_CAST_WARN inline bool operator<(const char *s) const;
1018 QT_ASCII_CAST_WARN inline bool operator<=(const char *s) const;
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
1022 QT_ASCII_CAST_WARN inline bool operator==(const QByteArray &s) const;
1023 QT_ASCII_CAST_WARN inline bool operator!=(const QByteArray &s) const;
1024 QT_ASCII_CAST_WARN inline bool operator<(const QByteArray &s) const;
1025 QT_ASCII_CAST_WARN inline bool operator>(const QByteArray &s) const;
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#else
1029 friend bool comparesEqual(const QString &lhs, QByteArrayView rhs) noexcept
1030 {
1031 return QString::compare_helper(lhs.constData(), lhs.size(),
1032 rhs.constData(), rhs.size()) == 0;
1033 }
1034 friend Qt::strong_ordering
1035 compareThreeWay(const QString &lhs, QByteArrayView rhs) noexcept
1036 {
1037 const int res = QString::compare_helper(lhs.constData(), lhs.size(),
1038 rhs.constData(), rhs.size());
1039 return Qt::compareThreeWay(res, 0);
1040 }
1041 Q_DECLARE_STRONGLY_ORDERED(QString, QByteArrayView, QT_ASCII_CAST_WARN)
1042
1043 friend bool comparesEqual(const QString &lhs, const QByteArray &rhs) noexcept
1044 { return comparesEqual(lhs, QByteArrayView(rhs)); }
1045 friend Qt::strong_ordering
1046 compareThreeWay(const QString &lhs, const QByteArray &rhs) noexcept
1047 {
1048 return compareThreeWay(lhs, QByteArrayView(rhs));
1049 }
1050 Q_DECLARE_STRONGLY_ORDERED(QString, QByteArray, QT_ASCII_CAST_WARN)
1051
1052 friend bool comparesEqual(const QString &lhs, const char *rhs) noexcept
1053 { return comparesEqual(lhs, QByteArrayView(rhs)); }
1054 friend Qt::strong_ordering
1055 compareThreeWay(const QString &lhs, const char *rhs) noexcept
1056 {
1057 return compareThreeWay(lhs, QByteArrayView(rhs));
1058 }
1059 Q_DECLARE_STRONGLY_ORDERED(QString, const char *, QT_ASCII_CAST_WARN)
1060#endif // QT_CORE_REMOVED_SINCE(6, 8)
1061
1062#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1063
1064 typedef QChar *iterator;
1065 typedef const QChar *const_iterator;
1066 typedef iterator Iterator;
1067 typedef const_iterator ConstIterator;
1068 typedef std::reverse_iterator<iterator> reverse_iterator;
1069 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1070 inline iterator begin();
1071 inline const_iterator begin() const;
1072 inline const_iterator cbegin() const;
1073 inline const_iterator constBegin() const;
1074 inline iterator end();
1075 inline const_iterator end() const;
1076 inline const_iterator cend() const;
1077 inline const_iterator constEnd() const;
1078 reverse_iterator rbegin() { return reverse_iterator(end()); }
1079 reverse_iterator rend() { return reverse_iterator(begin()); }
1080 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
1081 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
1082 const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
1083 const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
1084
1085 // STL compatibility
1086 typedef qsizetype size_type;
1087 typedef qptrdiff difference_type;
1088 typedef const QChar & const_reference;
1089 typedef QChar & reference;
1090 typedef QChar *pointer;
1091 typedef const QChar *const_pointer;
1092 typedef QChar value_type;
1093 inline void push_back(QChar c) { append(c); }
1094 inline void push_back(const QString &s) { append(s); }
1095 inline void push_front(QChar c) { prepend(c); }
1096 inline void push_front(const QString &s) { prepend(s); }
1097 void shrink_to_fit() { squeeze(); }
1098 iterator erase(const_iterator first, const_iterator last);
1099 inline iterator erase(const_iterator it) { return erase(it, it + 1); }
1100 constexpr qsizetype max_size() const noexcept
1101 {
1102 return maxSize();
1103 }
1104
1105 static inline QString fromStdString(const std::string &s);
1106 std::string toStdString() const;
1107 static inline QString fromStdWString(const std::wstring &s);
1108 inline std::wstring toStdWString() const;
1109
1110 static inline QString fromStdU16String(const std::u16string &s);
1111 inline std::u16string toStdU16String() const;
1112 static inline QString fromStdU32String(const std::u32string &s);
1113 inline std::u32string toStdU32String() const;
1114
1115 Q_IMPLICIT inline operator std::u16string_view() const noexcept;
1116
1117#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
1118 static QString fromCFString(CFStringRef string);
1119 CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED;
1120 static QString fromNSString(const NSString *string);
1121 NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED;
1122#endif
1123
1124#if defined(Q_OS_WASM) || defined(Q_QDOC)
1125 static QString fromEcmaString(emscripten::val jsString);
1126 emscripten::val toEcmaString() const;
1127#endif
1128
1129 constexpr bool isNull() const { return d.isNull(); }
1130
1131 bool isRightToLeft() const;
1132 [[nodiscard]] bool isValidUtf16() const noexcept
1133 { return QStringView(*this).isValidUtf16(); }
1134
1135 QString(qsizetype size, Qt::Initialization);
1136 explicit QString(DataPointer &&dd) : d(std::move(dd)) {}
1137
1138private:
1139#if defined(QT_NO_CAST_FROM_ASCII)
1140#define QSTRING_DECL_DELETED_ASCII_OP Q_DECL_EQ_DELETE_X("This function is not available under QT_NO_CAST_FROM_ASCII")
1141 QString &operator+=(const char *s) QSTRING_DECL_DELETED_ASCII_OP;
1142 QString &operator+=(const QByteArray &s) QSTRING_DECL_DELETED_ASCII_OP;
1143 QString(const char *ch) QSTRING_DECL_DELETED_ASCII_OP;
1144 QString(const QByteArray &a) QSTRING_DECL_DELETED_ASCII_OP;
1145 QString &operator=(const char *ch) QSTRING_DECL_DELETED_ASCII_OP;
1146 QString &operator=(const QByteArray &a) QSTRING_DECL_DELETED_ASCII_OP;
1147#undef QSTRING_DECL_DELETED_ASCII_OP
1148#endif
1149
1150 DataPointer d;
1151 static const char16_t _empty;
1152
1153 void reallocData(qsizetype alloc, QArrayData::AllocationOption option);
1154 void reallocGrowData(qsizetype n);
1155 // ### remove once QAnyStringView supports UTF-32:
1156 QString &assign_helper(const char32_t *data, qsizetype len);
1157 // Defined in qstringconverter.h
1158 template <typename InputIterator>
1159 void assign_helper_char8(InputIterator first, InputIterator last);
1160 static int compare_helper(const QChar *data1, qsizetype length1,
1161 const QChar *data2, qsizetype length2,
1162 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
1163 static int compare_helper(const QChar *data1, qsizetype length1,
1164 const char *data2, qsizetype length2,
1165 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
1166 static int localeAwareCompare_helper(const QChar *data1, qsizetype length1,
1167 const QChar *data2, qsizetype length2);
1168 static QString sliced_helper(QString &str, qsizetype pos, qsizetype n);
1169 static QString toLower_helper(const QString &str);
1170 static QString toLower_helper(QString &str);
1171 static QString toUpper_helper(const QString &str);
1172 static QString toUpper_helper(QString &str);
1173 static QString toCaseFolded_helper(const QString &str);
1174 static QString toCaseFolded_helper(QString &str);
1175 static QString trimmed_helper(const QString &str);
1176 static QString trimmed_helper(QString &str);
1177 static QString simplified_helper(const QString &str);
1178 static QString simplified_helper(QString &str);
1179 static QByteArray toLatin1_helper(const QString &);
1180 static QByteArray toLatin1_helper_inplace(QString &);
1181 static QByteArray toUtf8_helper(const QString &);
1182 static QByteArray toLocal8Bit_helper(const QChar *data, qsizetype size);
1183#if QT_CORE_REMOVED_SINCE(6, 6)
1184 static qsizetype toUcs4_helper(const ushort *uc, qsizetype length, uint *out);
1185#endif
1186 static qsizetype toUcs4_helper(const char16_t *uc, qsizetype length, char32_t *out);
1187 static qlonglong toIntegral_helper(QStringView string, bool *ok, int base);
1188 static qulonglong toIntegral_helper(QStringView string, bool *ok, uint base);
1189 template <typename Predicate>
1190 qsizetype removeIf_helper(Predicate pred)
1191 {
1192 const qsizetype result = d->eraseIf(pred);
1193 if (result > 0)
1194 d.data()[d.size] = u'\0';
1195 return result;
1196 }
1197
1198 friend class QStringView;
1199 friend class QByteArray;
1200 friend struct QAbstractConcatenable;
1201 template <typename T> friend qsizetype erase(QString &s, const T &t);
1202 template <typename Predicate> friend qsizetype erase_if(QString &s, Predicate pred);
1203
1204 template <typename T> static
1205 T toIntegral_helper(QStringView string, bool *ok, int base)
1206 {
1207 using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
1208 using Int32 = typename std::conditional<std::is_unsigned<T>::value, uint, int>::type;
1209
1210 // we select the right overload by casting base to int or uint
1211 Int64 val = toIntegral_helper(string, ok, Int32(base));
1212 if (T(val) != val) {
1213 if (ok)
1214 *ok = false;
1215 val = 0;
1216 }
1217 return T(val);
1218 }
1219
1220 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
1221 [[maybe_unused]] qsizetype n = 1) const
1222 {
1223 Q_ASSERT(pos >= 0);
1224 Q_ASSERT(pos <= d.size);
1225 Q_ASSERT(n >= 0);
1226 Q_ASSERT(n <= d.size - pos);
1227 }
1228
1229public:
1230 inline DataPointer &data_ptr() { return d; }
1231 inline const DataPointer &data_ptr() const { return d; }
1232};
1233
1234//
1235// QLatin1StringView inline members that require QUtf8StringView:
1236//
1237
1238int QLatin1StringView::compare(QUtf8StringView other, Qt::CaseSensitivity cs) const noexcept
1239{ return QtPrivate::compareStrings(*this, other, cs); }
1240
1241//
1242// QLatin1StringView inline members that require QString:
1243//
1244
1245QString QLatin1StringView::toString() const { return *this; }
1246
1247//
1248// QStringView inline members that require QUtf8StringView:
1249//
1250
1251int QStringView::compare(QUtf8StringView other, Qt::CaseSensitivity cs) const noexcept
1252{ return QtPrivate::compareStrings(*this, other, cs); }
1253
1254//
1255// QStringView inline members that require QString:
1256//
1257
1258QString QStringView::toString() const
1259{ return QString(*this); }
1260
1261qint64 QStringView::toLongLong(bool *ok, int base) const
1262{ return QString::toIntegral_helper<qint64>(*this, ok, base); }
1263quint64 QStringView::toULongLong(bool *ok, int base) const
1264{ return QString::toIntegral_helper<quint64>(*this, ok, base); }
1265long QStringView::toLong(bool *ok, int base) const
1266{ return QString::toIntegral_helper<long>(*this, ok, base); }
1267ulong QStringView::toULong(bool *ok, int base) const
1268{ return QString::toIntegral_helper<ulong>(*this, ok, base); }
1269int QStringView::toInt(bool *ok, int base) const
1270{ return QString::toIntegral_helper<int>(*this, ok, base); }
1271uint QStringView::toUInt(bool *ok, int base) const
1272{ return QString::toIntegral_helper<uint>(*this, ok, base); }
1273short QStringView::toShort(bool *ok, int base) const
1274{ return QString::toIntegral_helper<short>(*this, ok, base); }
1275ushort QStringView::toUShort(bool *ok, int base) const
1276{ return QString::toIntegral_helper<ushort>(*this, ok, base); }
1277
1278//
1279// QUtf8StringView inline members that require QStringView:
1280//
1281
1282template <bool UseChar8T>
1283int QBasicUtf8StringView<UseChar8T>::compare(QChar other, Qt::CaseSensitivity cs) const noexcept
1284{
1285 return QtPrivate::compareStrings(*this, QStringView(&other, 1), cs);
1286}
1287
1288template <bool UseChar8T>
1289int QBasicUtf8StringView<UseChar8T>::compare(QStringView other, Qt::CaseSensitivity cs) const noexcept
1290{
1291 return QtPrivate::compareStrings(*this, other, cs);
1292}
1293
1294template <bool UseChar8T>
1295[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QChar other) const noexcept
1296{
1297 return QtPrivate::equalStrings(*this, QStringView(&other, 1));
1298}
1299
1300template <bool UseChar8T>
1301[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QStringView other) const noexcept
1302{
1303 return QtPrivate::equalStrings(*this, other);
1304}
1305
1306//
1307// QUtf8StringView inline members that require QString, QL1SV or QBA:
1308//
1309
1310template <bool UseChar8T>
1311QString QBasicUtf8StringView<UseChar8T>::toString() const
1312{
1313 return QString::fromUtf8(data(), size());
1314}
1315
1316template<bool UseChar8T>
1317[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(QLatin1StringView other,
1318 Qt::CaseSensitivity cs) const noexcept
1319{
1320 return QtPrivate::compareStrings(*this, other, cs);
1321}
1322
1323template<bool UseChar8T>
1324[[nodiscard]] int QBasicUtf8StringView<UseChar8T>::compare(const QByteArray &other,
1325 Qt::CaseSensitivity cs) const noexcept
1326{
1327 return QtPrivate::compareStrings(*this,
1328 QBasicUtf8StringView<UseChar8T>(other.data(), other.size()),
1329 cs);
1330}
1331
1332template <bool UseChar8T>
1333[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(QLatin1StringView other) const noexcept
1334{
1335 return QtPrivate::equalStrings(*this, other);
1336}
1337
1338template <bool UseChar8T>
1339[[nodiscard]] bool QBasicUtf8StringView<UseChar8T>::equal(const QByteArray &other) const noexcept
1340{
1341 return size() == other.size()
1342 && QtPrivate::equalStrings(*this, QBasicUtf8StringView<UseChar8T>(other.data(),
1343 other.size()));
1344}
1345
1346//
1347// QAnyStringView inline members that require QString:
1348//
1349
1350QAnyStringView::QAnyStringView(const QByteArray &str) noexcept
1351 : QAnyStringView{str.begin(), str.size()} {}
1352QAnyStringView::QAnyStringView(const QString &str) noexcept
1353 : QAnyStringView{str.begin(), str.size()} {}
1354
1355QString QAnyStringView::toString() const
1356{ return QtPrivate::convertToQString(*this); }
1357
1358//
1359// QString inline members
1360//
1361QString::QString(QLatin1StringView latin1)
1362 : QString{QString::fromLatin1(latin1.data(), latin1.size())} {}
1363const QChar QString::at(qsizetype i) const
1364{ verify(i, 1); return QChar(d.data()[i]); }
1365const QChar QString::operator[](qsizetype i) const
1366{ verify(i, 1); return QChar(d.data()[i]); }
1367const QChar *QString::unicode() const
1368{ return data(); }
1369const QChar *QString::data() const
1370{
1371#if QT5_NULL_STRINGS == 1
1372 return reinterpret_cast<const QChar *>(d.data() ? d.data() : &_empty);
1373#else
1374 return reinterpret_cast<const QChar *>(d.data());
1375#endif
1376}
1377QChar *QString::data()
1378{
1379 detach();
1380 Q_ASSERT(d.data());
1381 return reinterpret_cast<QChar *>(d.data());
1382}
1383const QChar *QString::constData() const
1384{ return data(); }
1385void QString::detach()
1386{ if (d.needsDetach()) reallocData(d.size, QArrayData::KeepSize); }
1387bool QString::isDetached() const
1388{ return !d.isShared(); }
1389void QString::clear()
1390{ if (!isNull()) *this = QString(); }
1391QString::QString(const QString &other) noexcept : d(other.d)
1392{ }
1393qsizetype QString::capacity() const { return qsizetype(d.constAllocatedCapacity()); }
1394QString &QString::setNum(short n, int base)
1395{ return setNum(qlonglong(n), base); }
1396QString &QString::setNum(ushort n, int base)
1397{ return setNum(qulonglong(n), base); }
1398QString &QString::setNum(int n, int base)
1399{ return setNum(qlonglong(n), base); }
1400QString &QString::setNum(uint n, int base)
1401{ return setNum(qulonglong(n), base); }
1402QString &QString::setNum(long n, int base)
1403{ return setNum(qlonglong(n), base); }
1404QString &QString::setNum(ulong n, int base)
1405{ return setNum(qulonglong(n), base); }
1406QString &QString::setNum(float n, char f, int prec)
1407{ return setNum(double(n),f,prec); }
1408#if QT_CORE_REMOVED_SINCE(6, 9)
1409QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const
1410{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
1411QString QString::arg(uint a, int fieldWidth, int base, QChar fillChar) const
1412{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
1413QString QString::arg(long a, int fieldWidth, int base, QChar fillChar) const
1414{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
1415QString QString::arg(ulong a, int fieldWidth, int base, QChar fillChar) const
1416{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
1417QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) const
1418{ return arg(qlonglong(a), fieldWidth, base, fillChar); }
1419QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const
1420{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
1421#endif // QT_CORE_REMOVED_SINCE
1422
1423QString QString::section(QChar asep, qsizetype astart, qsizetype aend, SectionFlags aflags) const
1424{ return section(QString(asep), astart, aend, aflags); }
1425
1426QT_WARNING_PUSH
1427QT_WARNING_DISABLE_MSVC(4127) // "conditional expression is constant"
1428QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable"
1429
1430qsizetype QString::toWCharArray(wchar_t *array) const
1431{
1432 return qToStringViewIgnoringNull(*this).toWCharArray(array);
1433}
1434
1435qsizetype QStringView::toWCharArray(wchar_t *array) const
1436{
1437 if (sizeof(wchar_t) == sizeof(QChar)) {
1438 if (auto src = data())
1439 memcpy(array, src, sizeof(QChar) * size());
1440 return size();
1441 } else {
1442 return QString::toUcs4_helper(utf16(), size(), reinterpret_cast<char32_t *>(array));
1443 }
1444}
1445
1447
1448QString QString::fromWCharArray(const wchar_t *string, qsizetype size)
1449{
1450 if constexpr (sizeof(wchar_t) == sizeof(QChar)) {
1451 return QString(reinterpret_cast<const QChar *>(string), size);
1452 } else {
1453#ifdef QT_BOOTSTRAPPED
1454 Q_UNREACHABLE_RETURN(QString());
1455#else
1456 return fromUcs4(reinterpret_cast<const char32_t *>(string), size);
1457#endif
1458 }
1459}
1460
1461constexpr QString::QString() noexcept {}
1462QString::~QString() {}
1463
1464void QString::reserve(qsizetype asize)
1465{
1466 if (d.needsDetach() || asize >= capacity() - d.freeSpaceAtBegin())
1467 reallocData(qMax(asize, size()), QArrayData::KeepSize);
1468 if (d.constAllocatedCapacity())
1469 d.setFlag(Data::CapacityReserved);
1470}
1471
1472void QString::squeeze()
1473{
1474 if (!d.isMutable())
1475 return;
1476 if (d.needsDetach() || size() < capacity())
1477 reallocData(d.size, QArrayData::KeepSize);
1478 if (d.constAllocatedCapacity())
1479 d.clearFlag(Data::CapacityReserved);
1480}
1481
1482QChar &QString::operator[](qsizetype i)
1483{ verify(i, 1); return data()[i]; }
1484QChar &QString::front() { return operator[](0); }
1485QChar &QString::back() { return operator[](size() - 1); }
1486QString::iterator QString::begin()
1487{ detach(); return reinterpret_cast<QChar*>(d.data()); }
1488QString::const_iterator QString::begin() const
1489{ return reinterpret_cast<const QChar*>(d.data()); }
1490QString::const_iterator QString::cbegin() const
1491{ return reinterpret_cast<const QChar*>(d.data()); }
1492QString::const_iterator QString::constBegin() const
1493{ return reinterpret_cast<const QChar*>(d.data()); }
1494QString::iterator QString::end()
1495{ detach(); return reinterpret_cast<QChar*>(d.data() + d.size); }
1496QString::const_iterator QString::end() const
1497{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
1498QString::const_iterator QString::cend() const
1499{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
1500QString::const_iterator QString::constEnd() const
1501{ return reinterpret_cast<const QChar*>(d.data() + d.size); }
1502bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
1503{ return indexOf(s, 0, cs) != -1; }
1504bool QString::contains(QLatin1StringView s, Qt::CaseSensitivity cs) const
1505{ return indexOf(s, 0, cs) != -1; }
1506bool QString::contains(QChar c, Qt::CaseSensitivity cs) const
1507{ return indexOf(c, 0, cs) != -1; }
1508bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
1509{ return indexOf(s, 0, cs) != -1; }
1510
1511#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1512#if QT_CORE_REMOVED_SINCE(6, 8)
1513bool QString::operator==(const char *s) const
1514{ return QString::compare_helper(constData(), size(), s, -1) == 0; }
1515bool QString::operator!=(const char *s) const
1516{ return QString::compare_helper(constData(), size(), s, -1) != 0; }
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; }
1525
1526QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const
1527{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) == 0; }
1528QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const
1529{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) != 0; }
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; }
1538
1539bool QByteArray::operator==(const QString &s) const
1540{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) == 0; }
1541bool QByteArray::operator!=(const QString &s) const
1542{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; }
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; }
1551#endif // QT_CORE_REMOVED_SINCE(6, 8)
1552#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1553
1554#if !defined(QT_USE_FAST_OPERATOR_PLUS) && !defined(QT_USE_QSTRINGBUILDER)
1555// QString + QString
1556inline QString operator+(const QString &s1, const QString &s2)
1557{ QString t(s1); t += s2; return t; }
1558inline QString operator+(QString &&lhs, const QString &rhs)
1559{ return std::move(lhs += rhs); }
1560inline QString operator+(const QString &s1, QChar s2)
1561{ QString t(s1); t += s2; return t; }
1562inline QString operator+(QString &&lhs, QChar rhs)
1563{ return std::move(lhs += rhs); }
1564inline QString operator+(QChar s1, const QString &s2)
1565{ QString t(s1); t += s2; return t; }
1566inline QString operator+(const QString &lhs, QStringView rhs)
1567{
1568 QString ret{lhs.size() + rhs.size(), Qt::Uninitialized};
1569 return ret.assign(lhs).append(rhs);
1570}
1571inline QString operator+(QStringView lhs, const QString &rhs)
1572{
1573 QString ret{lhs.size() + rhs.size(), Qt::Uninitialized};
1574 return ret.assign(lhs).append(rhs);
1575}
1576
1577# if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
1578QT_ASCII_CAST_WARN inline QString operator+(const QString &s1, const char *s2)
1579{ QString t(s1); t += QUtf8StringView(s2); return t; }
1580QT_ASCII_CAST_WARN inline QString operator+(QString &&lhs, const char *rhs)
1581{ QT_IGNORE_DEPRECATIONS(return std::move(lhs += rhs);) }
1582QT_ASCII_CAST_WARN inline QString operator+(const char *s1, const QString &s2)
1583{ QString t = QString::fromUtf8(s1); t += s2; return t; }
1584QT_ASCII_CAST_WARN inline QString operator+(const QByteArray &ba, const QString &s)
1585{ QString t = QString::fromUtf8(ba); t += s; return t; }
1586QT_ASCII_CAST_WARN inline QString operator+(const QString &s, const QByteArray &ba)
1587{ QString t(s); t += QUtf8StringView(ba); return t; }
1588QT_ASCII_CAST_WARN inline QString operator+(QString &&lhs, const QByteArray &rhs)
1589{ QT_IGNORE_DEPRECATIONS(return std::move(lhs += rhs);) }
1590# endif // QT_NO_CAST_FROM_ASCII
1591#endif // QT_USE_QSTRINGBUILDER
1592
1593QString QString::fromStdString(const std::string &s)
1594{ return fromUtf8(s.data(), qsizetype(s.size())); }
1595
1596std::wstring QString::toStdWString() const
1597{
1598 std::wstring str;
1599 str.resize(size());
1600 str.resize(toWCharArray(str.data()));
1601 return str;
1602}
1603
1604QString QString::fromStdWString(const std::wstring &s)
1605{ return fromWCharArray(s.data(), qsizetype(s.size())); }
1606
1607QString QString::fromStdU16String(const std::u16string &s)
1608{ return fromUtf16(s.data(), qsizetype(s.size())); }
1609
1610std::u16string QString::toStdU16String() const
1611{ return std::u16string(reinterpret_cast<const char16_t*>(data()), size()); }
1612
1613QString QString::fromStdU32String(const std::u32string &s)
1614{ return fromUcs4(s.data(), qsizetype(s.size())); }
1615
1616std::u32string QString::toStdU32String() const
1617{
1618 std::u32string u32str(size(), char32_t(0));
1619 const qsizetype len = toUcs4_helper(reinterpret_cast<const char16_t *>(data()),
1620 size(), u32str.data());
1621 u32str.resize(len);
1622 return u32str;
1623}
1624
1625QString::operator std::u16string_view() const noexcept
1626{
1627 return std::u16string_view(d.data(), size_t(d.size));
1628}
1629
1630#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
1631Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QString &);
1632Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &);
1633#endif
1634
1636Q_DECLARE_OPERATORS_FOR_FLAGS(QString::SectionFlags)
1637
1638int QString::compare(QStringView s, Qt::CaseSensitivity cs) const noexcept
1639{ return -s.compare(*this, cs); }
1640
1641int QString::localeAwareCompare(QStringView s) const
1642{ return localeAwareCompare_helper(constData(), size(), s.constData(), s.size()); }
1643int QString::localeAwareCompare(QStringView s1, QStringView s2)
1644{ return localeAwareCompare_helper(s1.constData(), s1.size(), s2.constData(), s2.size()); }
1645int QStringView::localeAwareCompare(QStringView other) const
1646{ return QString::localeAwareCompare(*this, other); }
1647
1648#if QT_CORE_INLINE_IMPL_SINCE(6, 5)
1649qint64 QString::toLongLong(bool *ok, int base) const
1650{
1651 return toIntegral_helper<qlonglong>(*this, ok, base);
1652}
1653
1654quint64 QString::toULongLong(bool *ok, int base) const
1655{
1656 return toIntegral_helper<qulonglong>(*this, ok, base);
1657}
1658#endif
1659#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
1660qsizetype QString::indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
1661{
1662 return qToStringViewIgnoringNull(*this).indexOf(ch, from, cs);
1663}
1664qsizetype QString::lastIndexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
1665{
1666 return qToStringViewIgnoringNull(*this).lastIndexOf(ch, from, cs);
1667}
1668#endif
1669#if QT_CORE_INLINE_IMPL_SINCE(6, 10)
1670QString QString::fromRawData(const QChar *unicode, qsizetype size)
1671{
1672 return fromRawData(reinterpret_cast<const char16_t *>(unicode), size);
1673}
1674#endif
1675
1676namespace QtPrivate {
1677// used by qPrintable() and qUtf8Printable() macros
1678inline const QString &asString(const QString &s) { return s; }
1679inline QString &&asString(QString &&s) { return std::move(s); }
1680}
1681
1682#ifndef qPrintable
1683# define qPrintable(string) QtPrivate::asString(string).toLocal8Bit().constData()
1684#endif
1685
1686#ifndef qUtf8Printable
1687# define qUtf8Printable(string) QtPrivate::asString(string).toUtf8().constData()
1688#endif
1689
1690/*
1691 Wrap QString::utf16() with enough casts to allow passing it
1692 to QString::asprintf("%ls") without warnings.
1693*/
1694#ifndef qUtf16Printable
1695# define qUtf16Printable(string)
1696 static_cast<const wchar_t*>(static_cast<const void*>(QtPrivate::asString(string).utf16()))
1697#endif
1698
1699//
1700// QStringView::arg() implementation
1701//
1702
1703namespace QtPrivate {
1704
1705struct ArgBase {
1706 enum Tag : uchar { L1, Any, U16 } tag;
1707};
1708
1711 QStringViewArg() = default;
1712 constexpr explicit QStringViewArg(QStringView v) noexcept : ArgBase{U16}, string{v} {}
1713};
1714
1717 QLatin1StringArg() = default;
1718 constexpr explicit QLatin1StringArg(QLatin1StringView v) noexcept : ArgBase{L1}, string{v} {}
1719};
1720
1723 QAnyStringArg() = default;
1724 constexpr explicit QAnyStringArg(QAnyStringView v) noexcept : ArgBase{Any}, string{v} {}
1725};
1726
1727#if QT_CORE_REMOVED_SINCE(6, 9)
1730#endif
1731[[nodiscard]] Q_CORE_EXPORT QString argToQString(QAnyStringView pattern, size_t n, const ArgBase **args);
1732
1733template <typename...Args>
1734[[nodiscard]] Q_ALWAYS_INLINE QString argToQStringDispatch(QAnyStringView pattern, const Args &...args)
1735{
1736 const ArgBase *argBases[] = {&args..., /* avoid zero-sized array */ nullptr};
1737 return QtPrivate::argToQString(pattern, sizeof...(Args), argBases);
1738}
1739
1740constexpr inline QAnyStringArg qStringLikeToArg(QAnyStringView s) noexcept { return QAnyStringArg{s}; }
1741
1742} // namespace QtPrivate
1743
1744template <typename...Args>
1746QString QStringView::arg(Args &&...args) const
1747{
1748 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1749}
1750
1751template <typename...Args>
1753QString QLatin1StringView::arg(Args &&...args) const
1754{
1755 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1756}
1757
1758template <bool HasChar8T>
1759template <typename...Args>
1760QString QBasicUtf8StringView<HasChar8T>::arg(Args &&...args) const
1761{
1762 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1763}
1764
1765template <typename...Args>
1766QString QAnyStringView::arg(Args &&...args) const
1767{
1768 return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
1769}
1770
1771template <typename T>
1772qsizetype erase(QString &s, const T &t)
1773{
1774 return s.removeIf_helper([&t](const auto &e) { return t == e; });
1775}
1776
1777template <typename Predicate>
1778qsizetype erase_if(QString &s, Predicate pred)
1779{
1780 return s.removeIf_helper(pred);
1781}
1782
1783namespace Qt {
1784inline namespace Literals {
1785inline namespace StringLiterals {
1786inline QString operator""_s(const char16_t *str, size_t size) noexcept
1787{
1788 return QString(QStringPrivate(nullptr, const_cast<char16_t *>(str), qsizetype(size)));
1789}
1790
1791} // StringLiterals
1792} // Literals
1793} // Qt
1794
1795inline namespace QtLiterals {
1796#if QT_DEPRECATED_SINCE(6, 8)
1797
1798QT_DEPRECATED_VERSION_X_6_8("Use _s from Qt::StringLiterals namespace instead.")
1799inline QString operator""_qs(const char16_t *str, size_t size) noexcept
1800{
1801 return Qt::StringLiterals::operator""_s(str, size);
1802}
1803
1804#endif // QT_DEPRECATED_SINCE(6, 8)
1805} // QtLiterals
1806
1807// all our supported compilers support Unicode string literals,
1808// even if their Q_COMPILER_UNICODE_STRING has been revoked due
1809// to lacking stdlib support. But QStringLiteral only needs the
1810// core language feature, so just use u"" here unconditionally:
1811
1812#define QT_UNICODE_LITERAL(str) u"" str
1813
1814namespace QtPrivate {
1815template <qsizetype N>
1816Q_ALWAYS_INLINE static QStringPrivate qMakeStringPrivate(const char16_t (&literal)[N])
1817{
1818 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1819 auto str = const_cast<char16_t *>(literal);
1820 return { nullptr, str, N - 1 };
1821}
1822} // namespace QtPrivate
1823
1824#define QStringLiteral(str) (QString(QtPrivate::qMakeStringPrivate(QT_UNICODE_LITERAL(str)))) /**/
1825
1826QT_END_NAMESPACE
1827
1828#include <QtCore/qstringbuilder.h>
1829#include <QtCore/qstringconverter.h>
1830
1831#ifdef Q_L1S_VIEW_IS_PRIMARY
1832# undef Q_L1S_VIEW_IS_PRIMARY
1833#endif
1834
1835#endif // QSTRING_H
\inmodule QtCore\reentrant
Definition qdatastream.h:50
QString && asString(QString &&s)
Definition qstring.h:1679
constexpr QAnyStringArg qStringLikeToArg(QAnyStringView s) noexcept
Definition qstring.h:1740
const QString & asString(const QString &s)
Definition qstring.h:1678
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:1786
Definition qcompare.h:76
#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:99
QString operator+(const QString &s1, QChar s2)
Definition qstring.h:1560
QString operator+(QString &&lhs, const QString &rhs)
Definition qstring.h:1558
qsizetype erase_if(QString &s, Predicate pred)
Definition qstring.h:1778
#define QT_UNICODE_LITERAL(str)
Definition qstring.h:1812
QString operator+(QString &&lhs, QChar rhs)
Definition qstring.h:1562
QString operator+(QChar s1, const QString &s2)
Definition qstring.h:1564
QString operator+(const QString &s1, const QString &s2)
Definition qstring.h:1556
qsizetype erase(QString &s, const T &t)
Definition qstring.h:1772
QList< QList< qInternalCallback > > callbacks
Definition qglobal.cpp:128
constexpr QAnyStringArg(QAnyStringView v) noexcept
Definition qstring.h:1724
QAnyStringView string
Definition qstring.h:1722
QLatin1StringView string
Definition qstring.h:1716
constexpr QLatin1StringArg(QLatin1StringView v) noexcept
Definition qstring.h:1718
constexpr QStringViewArg(QStringView v) noexcept
Definition qstring.h:1712