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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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