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