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

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