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