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