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