1 /*
2  * DQt - D bindings for the Qt Toolkit
3  *
4  * GNU Lesser General Public License Usage
5  * This file may be used under the terms of the GNU Lesser
6  * General Public License version 3 as published by the Free Software
7  * Foundation and appearing in the file LICENSE.LGPL3 included in the
8  * packaging of this file. Please review the following information to
9  * ensure the GNU Lesser General Public License version 3 requirements
10  * will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
11  */
12 module qt.core.stringview;
13 extern(C++):
14 
15 import core.stdc.config;
16 import qt.config;
17 import qt.core.bytearray;
18 import qt.core.global;
19 import qt.core.list;
20 import qt.core.namespace;
21 import qt.core.qchar;
22 import qt.core.regularexpression;
23 import qt.core.string;
24 import qt.core.typeinfo;
25 import qt.helpers;
26 
27 /*
28     This macro enables three "levels" of QStringView support:
29 
30     1. offer QStringView, overload some functions taking QString with
31     QStringView
32 
33     2. Obsolete: QStringRef and its overloads have been removed.
34 
35     3. like 2, but replace functions taking QString, too.
36 */
37 /+ #ifndef QT_STRINGVIEW_LEVEL
38 #  define QT_STRINGVIEW_LEVEL 1
39 #endif
40 
41 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
42 Q_FORWARD_DECLARE_CF_TYPE(CFString);
43 Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
44 #endif +/
45 
46 
47 
48 extern(C++, "QtPrivate") {
49 /+ template <typename Char>
50 struct IsCompatibleCharTypeHelper
51     : std::integral_constant<bool,
52                              std::is_same<Char, QChar>::value ||
53                              std::is_same<Char, ushort>::value ||
54                              std::is_same<Char, char16_t>::value ||
55                              (std::is_same<Char, wchar_t>::value && sizeof(wchar_t) == sizeof(QChar))> {};
56 template <typename Char>
57 struct IsCompatibleCharType
58     : IsCompatibleCharTypeHelper<typename std::remove_cv<typename std::remove_reference<Char>::type>::type> {};
59 
60 template <typename Pointer>
61 struct IsCompatiblePointerHelper : std::false_type {};
62 template <typename Char>
63 struct IsCompatiblePointerHelper<Char*>
64     : IsCompatibleCharType<Char> {};
65 template <typename Pointer>
66 struct IsCompatiblePointer
67     : IsCompatiblePointerHelper<typename std::remove_cv<typename std::remove_reference<Pointer>::type>::type> {}; +/
68 
69 struct IsContainerCompatibleWithQStringView(T, Enable) {
70     /+ std:: +/false_type base0;
71     alias base0 this;
72 }
73 
74 /+ template <typename T>
75 struct IsContainerCompatibleWithQStringView<T, std::enable_if_t<std::conjunction_v<
76             // lacking concepts and ranges, we accept any T whose std::data yields a suitable pointer ...
77             IsCompatiblePointer<decltype( std::data(std::declval<const T &>()) )>,
78             // ... and that has a suitable size ...
79             std::is_convertible<decltype( std::size(std::declval<const T &>()) ), qsizetype>,
80             // ... and it's a range as it defines an iterator-like API
81             IsCompatibleCharType<typename std::iterator_traits<decltype( std::begin(std::declval<const T &>()) )>::value_type>,
82             std::is_convertible<
83                 decltype( std::begin(std::declval<const T &>()) != std::end(std::declval<const T &>()) ),
84                 bool>,
85 
86             // These need to be treated specially due to the empty vs null distinction
87             std::negation<std::is_same<std::decay_t<T>, QString>>,
88 
89             // Don't make an accidental copy constructor
90             std::negation<std::is_same<std::decay_t<T>, QStringView>>
91         >>> : std::true_type {}; +/
92 
93 } // namespace QtPrivate
94 
95 /// Binding for C++ class [QStringView](https://doc.qt.io/qt-6/qstringview.html).
96 @Q_PRIMITIVE_TYPE extern(C++, class) struct QStringView
97 {
98 public:
99     alias storage_type = wchar;
100     alias value_type = const(QChar);
101     alias difference_type = /+ std:: +/ptrdiff_t;
102     alias size_type = qsizetype;
103     /+ typedef value_type &reference; +/
104     /+ typedef value_type &const_reference; +/
105     alias pointer = value_type*;
106     alias const_pointer = value_type*;
107 
108     alias iterator = pointer;
109     alias const_iterator = const_pointer;
110     /+ typedef std::reverse_iterator<iterator> reverse_iterator; +/
111     /+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator; +/
112 
113 private:
114     /+ template <typename Char> +/
115     /+ using if_compatible_char = typename std::enable_if<QtPrivate::IsCompatibleCharType<Char>::value, bool>::type; +/
116 
117     /+ template <typename Pointer> +/
118     /+ using if_compatible_pointer = typename std::enable_if<QtPrivate::IsCompatiblePointer<Pointer>::value, bool>::type; +/
119 
120     /+ template <typename T> +/
121     /+ using if_compatible_qstring_like = typename std::enable_if<std::is_same<T, QString>::value, bool>::type; +/
122 
123     /+ template <typename T> +/
124     alias if_compatible_container(T) = UnknownType!q{/+ std:: +/enable_if!(/+ QtPrivate:: +/IsContainerCompatibleWithQStringView!(T).value, bool).type};
125 
126     /+ template <typename Char> +/
127     /+ static qsizetype lengthHelperPointer(const Char *str) noexcept
128     {
129 #if defined(__cpp_lib_is_constant_evaluated)
130         if (std::is_constant_evaluated())
131             return std::char_traits<Char>::length(str);
132 #elif defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
133         if (__builtin_constant_p(*str))
134             return std::char_traits<Char>::length(str);
135 #endif
136         return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
137     } +/
138     /+ static qsizetype lengthHelperPointer(const QChar *str) noexcept
139     {
140         return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
141     } +/
142 
143     /+ template <typename Container> +/
144     static qsizetype lengthHelperContainer(Container)(ref const(Container) c)/+ noexcept+/
145     {
146         return qsizetype(/+ std:: +/size(c));
147     }
148 
149     /+ template <typename Char, size_t N> +/
150     static qsizetype lengthHelperContainer(Char,size_t N)(ref const(Char)[N] str)/+ noexcept+/
151     {
152         const it = /+ std:: +/char_traits!(Char).find(str.ptr, N, Char(0));
153         const end = it ? it : /+ std:: +/end(str);
154         return qsizetype(/+ std:: +/distance(str, end));
155     }
156 
157     /+ template <typename Char> +/
158     static const(storage_type)* castHelper(Char)(const(Char)* str)/+ noexcept+/
159     { return reinterpret_cast!(const(storage_type)*)(str); }
160     static const(storage_type)* castHelper(const(storage_type)* str)/+ noexcept+/
161     { return str; }
162 
163 public:
164     /+this()/+ noexcept+/
165     {
166         this.m_size = 0;
167         this.m_data = null;
168     }+/
169     this(typeof(null))/+ noexcept+/
170     {
171         //this();
172     }
173 
174     /+ template <typename Char, if_compatible_char<Char> = true> +/
175     this(Char,)(const(Char)* str, qsizetype len)
176     {
177         this.m_size = ((){(){ (mixin(Q_ASSERT(q{len >= 0})));
178         return /+ Q_ASSERT(str || !len) +/ mixin(Q_ASSERT(q{str || !len}));
179         }();
180         return len;
181         }());
182         this.m_data = castHelper(str);
183     }
184 
185     /+ template <typename Char, if_compatible_char<Char> = true> +/
186     this(Char,)(const(Char)* f, const(Char)* l)
187     {
188         this(f, l - f);
189     }
190 
191 /+ #ifdef Q_CLANG_QDOC
192     template <typename Char, size_t N>
193     constexpr QStringView(const Char (&array)[N]) noexcept;
194 
195     template <typename Char>
196     constexpr QStringView(const Char *str) noexcept;
197 #else +/
198 
199     /+ template <typename Pointer, if_compatible_pointer<Pointer> = true> +/
200     this(Pointer,)(ref const(Pointer) str)/+ noexcept+/ if(is(Pointer: const(wchar)*))
201     {
202         this(str, str ? lengthHelperPointer(str) : 0);
203     }
204 /+ #endif
205 
206 #ifdef Q_CLANG_QDOC
207     QStringView(const QString &str) noexcept;
208 #else +/
209     /+ template <typename String, if_compatible_qstring_like<String> = true> +/
210     this(String)(ref const(String) str)/+ noexcept+/
211     {
212         this(str.isNull() ? null : str.data(), qsizetype(str.size()));
213     }
214 /+ #endif +/
215 
216     /+ template <typename Container, if_compatible_container<Container> = true> +/
217     /+this(Container,)(ref const(Container) c)/+ noexcept+/
218     {
219         this(/+ std:: +/data(c), lengthHelperContainer(c));
220     }+/
221 
222     /+ template <typename Char, size_t Size, if_compatible_char<Char> = true> +/
223     /+ [[nodiscard]] +/ static QStringView fromArray(Char,size_t Size,)(ref const(Char)[Size] string)/+ noexcept+/
224     { return QStringView(string.ptr, Size); }
225 
226     /+ [[nodiscard]] +/ pragma(inline, true) QString toString() const
227     { return (){ (mixin(Q_ASSERT(q{QStringView.size() == QStringView.length()})));
228     return QString(data(), length());
229     }(); } // defined in qstring.h
230     static if((versionIsSet!("OSX") || versionIsSet!("iOS") || versionIsSet!("TVOS") || versionIsSet!("WatchOS")))
231     {
232         // defined in qcore_foundation.mm
233         /+ [[nodiscard]] Q_CORE_EXPORT CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED; +/
234         /+ [[nodiscard]] Q_CORE_EXPORT NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED; +/
235     }
236 
237     /+ [[nodiscard]] +/ qsizetype size() const/+ noexcept+/ { return m_size; }
238     /+ [[nodiscard]] +/ const_pointer data() const/+ noexcept+/ { return reinterpret_cast!(const_pointer)(m_data); }
239     /+ [[nodiscard]] +/ const_pointer constData() const/+ noexcept+/ { return data(); }
240     /+ [[nodiscard]] +/ const(storage_type)* utf16() const/+ noexcept+/ { return m_data; }
241 
242     /+ [[nodiscard]] +/ QChar opIndex(qsizetype n) const
243     { return (){(){ (mixin(Q_ASSERT(q{n >= 0})));
244 return /+ Q_ASSERT(n < size()) +/ mixin(Q_ASSERT(q{n < QStringView.size()}));
245 }();
246 return QChar(m_data[n]);
247 }(); }
248 
249     //
250     // QString API
251     //
252 
253     /+ template <typename...Args> +/
254     /+ [[nodiscard]] inline QString arg(Args &&...args) const; +/ // defined in qstring.h
255 
256     /+ [[nodiscard]] +/ QByteArray toLatin1() const {
257         import qt.core.stringalgorithms;
258         return /+ QtPrivate:: +/qt.core.stringalgorithms.convertToLatin1(this);
259     }
260     /+ [[nodiscard]] +/ QByteArray toUtf8() const {
261         import qt.core.stringalgorithms;
262         return /+ QtPrivate:: +/qt.core.stringalgorithms.convertToUtf8(this);
263     }
264     /+ [[nodiscard]] +/ QByteArray toLocal8Bit() const {
265         import qt.core.stringalgorithms;
266         return /+ QtPrivate:: +/qt.core.stringalgorithms.convertToLocal8Bit(this);
267     }
268     // ### Qt 7 char32_t
269     /+ [[nodiscard]] +/ pragma(inline, true) QList!(uint) toUcs4() const {
270         import qt.core.stringalgorithms;
271         return /+ QtPrivate:: +/qt.core.stringalgorithms.convertToUcs4(this);
272     } // defined in qlist.h ### Qt 7 char32_t
273 
274     /+ [[nodiscard]] +/ QChar at(qsizetype n) const/+ noexcept+/ { return (this)[n]; }
275 
276 /+    /+ [[nodiscard]] +/ QStringView mid(qsizetype pos, qsizetype n = -1) const/+ noexcept+/
277     {
278         //using namespace QtPrivate;
279         auto result = QContainerImplHelper.mid(size(), &pos, &n);
280         return result == QContainerImplHelper.Null ? QStringView() : QStringView(m_data + pos, n);
281     }+/
282     /+ [[nodiscard]] +/ QStringView left(qsizetype n) const/+ noexcept+/
283     {
284         if (size_t(n) >= size_t(size()))
285             n = size();
286         return QStringView(m_data, n);
287     }
288     /+ [[nodiscard]] +/ QStringView right(qsizetype n) const/+ noexcept+/
289     {
290         if (size_t(n) >= size_t(size()))
291             n = size();
292         return QStringView(m_data + m_size - n, n);
293     }
294 
295     /+ [[nodiscard]] +/ QStringView first(qsizetype n) const/+ noexcept+/
296     { (mixin(Q_ASSERT(q{n >= 0}))); (mixin(Q_ASSERT(q{n <= QStringView.size()}))); return QStringView(m_data, n); }
297     /+ [[nodiscard]] +/ QStringView last(qsizetype n) const/+ noexcept+/
298     { (mixin(Q_ASSERT(q{n >= 0}))); (mixin(Q_ASSERT(q{n <= QStringView.size()}))); return QStringView(m_data + size() - n, n); }
299     /+ [[nodiscard]] +/ QStringView sliced(qsizetype pos) const/+ noexcept+/
300     { (mixin(Q_ASSERT(q{pos >= 0}))); (mixin(Q_ASSERT(q{pos <= QStringView.size()}))); return QStringView(m_data + pos, size() - pos); }
301     /+ [[nodiscard]] +/ QStringView sliced(qsizetype pos, qsizetype n) const/+ noexcept+/
302     { (mixin(Q_ASSERT(q{pos >= 0}))); (mixin(Q_ASSERT(q{n >= 0}))); (mixin(Q_ASSERT(q{size_t(pos) + size_t(n) <= size_t(QStringView.size())}))); return QStringView(m_data + pos, n); }
303     /+ [[nodiscard]] +/ QStringView chopped(qsizetype n) const/+ noexcept+/
304     { return (){(){ (mixin(Q_ASSERT(q{n >= 0})));
305 return /+ Q_ASSERT(n <= size()) +/ mixin(Q_ASSERT(q{n <= QStringView.size()}));
306 }();
307 return QStringView(m_data, m_size - n);
308 }(); }
309 
310     void truncate(qsizetype n)/+ noexcept+/
311     { (mixin(Q_ASSERT(q{n >= 0}))); (mixin(Q_ASSERT(q{n <= QStringView.size()}))); m_size = n; }
312     void chop(qsizetype n)/+ noexcept+/
313     { (mixin(Q_ASSERT(q{n >= 0}))); (mixin(Q_ASSERT(q{n <= QStringView.size()}))); m_size -= n; }
314 
315     /+ [[nodiscard]] +/ QStringView trimmed() const/+ noexcept+/ {
316         import qt.core.stringalgorithms;
317         return /+ QtPrivate:: +/qt.core.stringalgorithms.trimmed(this);
318     }
319 
320     /+ template <typename Needle, typename...Flags> +/
321     /+ [[nodiscard]] constexpr inline auto tokenize(Needle &&needle, Flags...flags) const
322         noexcept(noexcept(qTokenize(std::declval<const QStringView&>(), std::forward<Needle>(needle), flags...)))
323             -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
324     { return qTokenize(*this, std::forward<Needle>(needle), flags...); } +/
325 
326     /+ [[nodiscard]] +/ int compare(QStringView other, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
327     {
328         import qt.core.stringalgorithms;
329         return /+ QtPrivate:: +/qt.core.stringalgorithms.compareStrings(this, other, cs);
330     }
331     //
332     // QStringView members that require QLatin1String:
333     //
334     /+ [[nodiscard]] +/ pragma(inline, true) int compare(QLatin1String s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
335     {
336         import qt.core.stringalgorithms;
337         return /+ QtPrivate:: +/qt.core.stringalgorithms.compareStrings(this, s, cs);
338     }
339     /+ [[nodiscard]] +/ int compare(QChar c) const/+ noexcept+/
340     { return size() >= 1 ? compare_single_char_helper(*utf16() - c.unicode()) : -1; }
341     /+ [[nodiscard]] +/ int compare(QChar c, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs) const/+ noexcept+/
342     {
343         import qt.core.stringalgorithms;
344         return /+ QtPrivate:: +/qt.core.stringalgorithms.compareStrings(this, QStringView(&c, 1), cs);
345     }
346 
347     /+ [[nodiscard]] +/ bool startsWith(QStringView s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
348     {
349         import qt.core.stringalgorithms;
350         return /+ QtPrivate:: +/qt.core.stringalgorithms.startsWith(this, s, cs);
351     }
352     /+ [[nodiscard]] +/ pragma(inline, true) bool startsWith(QLatin1String s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
353     {
354         import qt.core.stringalgorithms;
355         return /+ QtPrivate:: +/qt.core.stringalgorithms.startsWith(this, s, cs);
356     }
357     /+ [[nodiscard]] +/ bool startsWith(QChar c) const/+ noexcept+/
358     { return !empty() && front() == c; }
359     /+ [[nodiscard]] +/ bool startsWith(QChar c, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs) const/+ noexcept+/
360     {
361         import qt.core.stringalgorithms;
362         return /+ QtPrivate:: +/qt.core.stringalgorithms.startsWith(this, QStringView(&c, 1), cs);
363     }
364 
365     /+ [[nodiscard]] +/ bool endsWith(QStringView s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
366     {
367         import qt.core.stringalgorithms;
368         return /+ QtPrivate:: +/qt.core.stringalgorithms.endsWith(this, s, cs);
369     }
370     /+ [[nodiscard]] +/ pragma(inline, true) bool endsWith(QLatin1String s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
371     {
372         import qt.core.stringalgorithms;
373         return /+ QtPrivate:: +/qt.core.stringalgorithms.endsWith(this, s, cs);
374     }
375     /+ [[nodiscard]] +/ bool endsWith(QChar c) const/+ noexcept+/
376     { return !empty() && back() == c; }
377     /+ [[nodiscard]] +/ bool endsWith(QChar c, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs) const/+ noexcept+/
378     {
379         import qt.core.stringalgorithms;
380         return /+ QtPrivate:: +/qt.core.stringalgorithms.endsWith(this, QStringView(&c, 1), cs);
381     }
382 
383     /+ [[nodiscard]] +/ qsizetype indexOf(QChar c, qsizetype from = 0, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
384     {
385         import qt.core.stringalgorithms;
386         return /+ QtPrivate:: +/qt.core.stringalgorithms.findString(this, from, QStringView(&c, 1), cs);
387     }
388     /+ [[nodiscard]] +/ qsizetype indexOf(QStringView s, qsizetype from = 0, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
389     {
390         import qt.core.stringalgorithms;
391         return /+ QtPrivate:: +/qt.core.stringalgorithms.findString(this, from, s, cs);
392     }
393     /+ [[nodiscard]] +/ pragma(inline, true) qsizetype indexOf(QLatin1String s, qsizetype from = 0, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
394     {
395         import qt.core.stringalgorithms;
396         return /+ QtPrivate:: +/qt.core.stringalgorithms.findString(this, from, s, cs);
397     }
398 
399     /+ [[nodiscard]] +/ bool contains(QChar c, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
400     { return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); }
401     /+ [[nodiscard]] +/ bool contains(QStringView s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
402     { return indexOf(s, 0, cs) != qsizetype(-1); }
403     /+ [[nodiscard]] +/ pragma(inline, true) bool contains(QLatin1String s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
404     { return indexOf(s, 0, cs) != qsizetype(-1); }
405 
406     /+ [[nodiscard]] +/ qsizetype count(QChar c, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
407     {
408         import qt.core.stringalgorithms;
409         return /+ QtPrivate:: +/qt.core.stringalgorithms.count(this, c, cs);
410     }
411     /+ [[nodiscard]] +/ qsizetype count(QStringView s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
412     {
413         import qt.core.stringalgorithms;
414         return /+ QtPrivate:: +/qt.core.stringalgorithms.count(this, s, cs);
415     }
416 
417     /+ [[nodiscard]] +/ qsizetype lastIndexOf(QChar c, qsizetype from = -1, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
418     {
419         import qt.core.bytearrayalgorithms;
420         import qt.core.stringalgorithms;
421         return /+ QtPrivate:: +/qt.core.stringalgorithms.lastIndexOf(this, from, QStringView(&c, 1), cs);
422     }
423     /+ [[nodiscard]] +/ qsizetype lastIndexOf(QStringView s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
424     { return lastIndexOf(s, size(), cs); }
425     /+ [[nodiscard]] +/ qsizetype lastIndexOf(QStringView s, qsizetype from, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
426     {
427         import qt.core.bytearrayalgorithms;
428         import qt.core.stringalgorithms;
429         return /+ QtPrivate:: +/qt.core.stringalgorithms.lastIndexOf(this, from, s, cs);
430     }
431     /+ [[nodiscard]] +/ pragma(inline, true) qsizetype lastIndexOf(QLatin1String s, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
432     {
433         import qt.core.bytearrayalgorithms;
434         import qt.core.stringalgorithms;
435         return /+ QtPrivate:: +/qt.core.stringalgorithms.lastIndexOf(this, size(), s, cs);
436     }
437     /+ [[nodiscard]] +/ pragma(inline, true) qsizetype lastIndexOf(QLatin1String s, qsizetype from, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const/+ noexcept+/
438     {
439         import qt.core.bytearrayalgorithms;
440         import qt.core.stringalgorithms;
441         return /+ QtPrivate:: +/qt.core.stringalgorithms.lastIndexOf(this, from, s, cs);
442     }
443 
444 /+ #if QT_CONFIG(regularexpression) +/
445     /+ [[nodiscard]] +/ qsizetype indexOf(ref const(QRegularExpression) re, qsizetype from = 0, QRegularExpressionMatch* rmatch = null) const
446     {
447         import qt.core.stringalgorithms;
448 
449         return /+ QtPrivate:: +/qt.core.stringalgorithms.indexOf(this, re, from, rmatch);
450     }
451 /+ #ifdef Q_QDOC
452     [[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const;
453 #else +/
454     // prevent an ambiguity when called like this: lastIndexOf(re, 0)
455     /+ template <typename T = QRegularExpressionMatch, std::enable_if_t<std::is_same_v<T, QRegularExpressionMatch>, bool> = false> +/
456     /+ [[nodiscard]] +/ qsizetype lastIndexOf(T,)(ref const(QRegularExpression) re, T* rmatch = null) const
457     {
458         import qt.core.bytearrayalgorithms;
459         import qt.core.stringalgorithms;
460 
461         return /+ QtPrivate:: +/qt.core.stringalgorithms.lastIndexOf(this, re, size(), rmatch);
462     }
463 /+ #endif +/
464     /+ [[nodiscard]] +/ qsizetype lastIndexOf(ref const(QRegularExpression) re, qsizetype from, QRegularExpressionMatch* rmatch = null) const
465     {
466         import qt.core.bytearrayalgorithms;
467         import qt.core.stringalgorithms;
468 
469         return /+ QtPrivate:: +/qt.core.stringalgorithms.lastIndexOf(this, re, from, rmatch);
470     }
471     /+ [[nodiscard]] +/ bool contains(ref const(QRegularExpression) re, QRegularExpressionMatch* rmatch = null) const
472     {
473         import qt.core.stringalgorithms;
474 
475         return /+ QtPrivate:: +/qt.core.stringalgorithms.contains(this, re, rmatch);
476     }
477     /+ [[nodiscard]] +/ qsizetype count(ref const(QRegularExpression) re) const
478     {
479         import qt.core.stringalgorithms;
480 
481         return /+ QtPrivate:: +/qt.core.stringalgorithms.count(this, re);
482     }
483 /+ #endif +/
484 
485     /+ [[nodiscard]] +/ bool isRightToLeft() const/+ noexcept+/
486     {
487         import qt.core.stringalgorithms;
488         return /+ QtPrivate:: +/qt.core.stringalgorithms.isRightToLeft(this);
489     }
490     /+ [[nodiscard]] +/ bool isValidUtf16() const/+ noexcept+/
491     {
492         import qt.core.stringalgorithms;
493         return /+ QtPrivate:: +/qt.core.stringalgorithms.isValidUtf16(this);
494     }
495 
496     /+ [[nodiscard]] +/ pragma(inline, true) short toShort(bool* ok = null, int base = 10) const
497     { return QString.toIntegral_helper!(short)(this, ok, base); }
498     /+ [[nodiscard]] +/ pragma(inline, true) ushort toUShort(bool* ok = null, int base = 10) const
499     { return QString.toIntegral_helper!(ushort)(this, ok, base); }
500     /+ [[nodiscard]] +/ pragma(inline, true) int toInt(bool* ok = null, int base = 10) const
501     { return QString.toIntegral_helper!(int)(this, ok, base); }
502     /+ [[nodiscard]] +/ pragma(inline, true) uint toUInt(bool* ok = null, int base = 10) const
503     { return QString.toIntegral_helper!(uint)(this, ok, base); }
504     /+ [[nodiscard]] +/ pragma(inline, true) cpp_long toLong(bool* ok = null, int base = 10) const
505     { return QString.toIntegral_helper!(cpp_long)(this, ok, base); }
506     /+ [[nodiscard]] +/ pragma(inline, true) cpp_ulong toULong(bool* ok = null, int base = 10) const
507     { return QString.toIntegral_helper!(cpp_ulong)(this, ok, base); }
508     /+ [[nodiscard]] +/ pragma(inline, true) qlonglong toLongLong(bool* ok = null, int base = 10) const
509     /+pragma(inline, true) qint64 toLongLong(bool* ok, int base) const+/
510     { return QString.toIntegral_helper!(qint64)(this, ok, base); }
511     /+ [[nodiscard]] +/ pragma(inline, true) qulonglong toULongLong(bool* ok = null, int base = 10) const
512     /+pragma(inline, true) quint64 toULongLong(bool* ok, int base) const+/
513     { return QString.toIntegral_helper!(quint64)(this, ok, base); }
514     /+ [[nodiscard]] +/ /+ Q_CORE_EXPORT +/ float toFloat(bool* ok = null) const;
515     /+ [[nodiscard]] +/ /+ Q_CORE_EXPORT +/ double toDouble(bool* ok = null) const;
516 
517 /+    /+ [[nodiscard]] +/ pragma(inline, true) qsizetype toWCharArray(wchar_t* array) const
518     {
519         import core.stdc.string;
520 
521         if (wchar_t.sizeof == QChar.sizeof) {
522             if (auto src = data())
523                 memcpy(array, cast(const(void)*)(src), QChar.sizeof * size());
524             return size();
525         } else {
526             return QString.toUcs4_helper(reinterpret_cast!(const(ushort)*)(data()), size(),
527                                           reinterpret_cast!(uint*)(array));
528         }
529     } // defined in qstring.h +/
530 
531 
532     /+ [[nodiscard]] +/ /+ Q_CORE_EXPORT +/
533         QList!(QStringView) split(QStringView sep,
534                                  /+ Qt:: +/qt.core.namespace.SplitBehavior behavior = /+ Qt:: +/qt.core.namespace.SplitBehaviorFlags.KeepEmptyParts,
535                                  /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const;
536     /+ [[nodiscard]] +/ /+ Q_CORE_EXPORT +/
537         QList!(QStringView) split(QChar sep, /+ Qt:: +/qt.core.namespace.SplitBehavior behavior = /+ Qt:: +/qt.core.namespace.SplitBehaviorFlags.KeepEmptyParts,
538                                  /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseSensitive) const;
539 
540 /+ #if QT_CONFIG(regularexpression) +/
541     /+ [[nodiscard]] +/ /+ Q_CORE_EXPORT +/
542         QList!(QStringView) split(ref const(QRegularExpression) sep,
543                                  /+ Qt:: +/qt.core.namespace.SplitBehavior behavior = /+ Qt:: +/qt.core.namespace.SplitBehaviorFlags.KeepEmptyParts) const;
544 /+ #endif +/
545 
546     // QStringView <> QStringView
547     /+ friend bool operator==(QStringView lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); } +/
548     /+ friend bool operator!=(QStringView lhs, QStringView rhs) noexcept { return !(lhs == rhs); } +/
549     /+ friend bool operator< (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <  0; } +/
550     /+ friend bool operator<=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; } +/
551     /+ friend bool operator> (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >  0; } +/
552     /+ friend bool operator>=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; } +/
553 
554     // QStringView <> QChar
555     /+ friend bool operator==(QStringView lhs, QChar rhs) noexcept { return lhs == QStringView(&rhs, 1); } +/
556     /+ friend bool operator!=(QStringView lhs, QChar rhs) noexcept { return lhs != QStringView(&rhs, 1); } +/
557     /+ friend bool operator< (QStringView lhs, QChar rhs) noexcept { return lhs <  QStringView(&rhs, 1); } +/
558     /+ friend bool operator<=(QStringView lhs, QChar rhs) noexcept { return lhs <= QStringView(&rhs, 1); } +/
559     /+ friend bool operator> (QStringView lhs, QChar rhs) noexcept { return lhs >  QStringView(&rhs, 1); } +/
560     /+ friend bool operator>=(QStringView lhs, QChar rhs) noexcept { return lhs >= QStringView(&rhs, 1); } +/
561 
562     /+ friend bool operator==(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) == rhs; } +/
563     /+ friend bool operator!=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) != rhs; } +/
564     /+ friend bool operator< (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) <  rhs; } +/
565     /+ friend bool operator<=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) <= rhs; } +/
566     /+ friend bool operator> (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) >  rhs; } +/
567     /+ friend bool operator>=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) >= rhs; } +/
568 
569     //
570     // STL compatibility API:
571     //
572     /+ [[nodiscard]] +/ const_iterator begin()   const/+ noexcept+/ { return data(); }
573     /+ [[nodiscard]] +/ const_iterator end()     const/+ noexcept+/ { return data() + size(); }
574     /+ [[nodiscard]] +/ const_iterator cbegin()  const/+ noexcept+/ { return begin(); }
575     /+ [[nodiscard]] +/ const_iterator cend()    const/+ noexcept+/ { return end(); }
576     /+ [[nodiscard]] const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); } +/
577     /+ [[nodiscard]] const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); } +/
578     /+ [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); } +/
579     /+ [[nodiscard]] const_reverse_iterator crend()   const noexcept { return rend(); } +/
580 
581     /+ [[nodiscard]] +/ bool empty() const/+ noexcept+/ { return size() == 0; }
582     /+ [[nodiscard]] +/ QChar front() const { return (){ (mixin(Q_ASSERT(q{!QStringView.empty()})));
583 return QChar(m_data[0]);
584 }(); }
585     /+ [[nodiscard]] +/ QChar back()  const { return (){ (mixin(Q_ASSERT(q{!QStringView.empty()})));
586 return QChar(m_data[m_size - 1]);
587 }(); }
588 
589     //
590     // Qt compatibility API:
591     //
592     /+ [[nodiscard]] +/ const_iterator constBegin() const/+ noexcept+/ { return begin(); }
593     /+ [[nodiscard]] +/ const_iterator constEnd() const/+ noexcept+/ { return end(); }
594     /+ [[nodiscard]] +/ bool isNull() const/+ noexcept+/ { return !m_data; }
595     /+ [[nodiscard]] +/ bool isEmpty() const/+ noexcept+/ { return empty(); }
596     /+ [[nodiscard]] +/ qsizetype length() const/+ noexcept+/
597     { return size(); }
598     /+ [[nodiscard]] +/ QChar first() const { return front(); }
599     /+ [[nodiscard]] +/ QChar last()  const { return back(); }
600 private:
601     qsizetype m_size = 0;
602     const(storage_type)* m_data = null;
603 
604     int compare_single_char_helper(int diff) const/+ noexcept+/
605     { return diff ? diff : size() > 1 ? 1 : 0; }
606     mixin(CREATE_CONVENIENCE_WRAPPERS);
607 }
608 /+ Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE); +/
609 
610 pragma(inline, true) QStringView qToStringViewIgnoringNull(QStringLike, /+ typename std::enable_if<
611     std::is_same<QStringLike, QString>::value,
612     bool>::type +/ /+ = true +/)(ref const(QStringLike) s)/+ noexcept+/
613 { return QStringView(s.data(), s.size()); }
614 
615 // QChar inline functions:
616