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.iterable; 13 extern(C++): 14 15 import qt.config; 16 import qt.core.global; 17 import qt.core.taggedpointer; 18 import qt.helpers; 19 20 extern(C++, "QtPrivate") { 21 class QConstPreservingPointer(Type, Storage) 22 { 23 private: 24 enum Tag : bool { Const, Mutable } 25 QTaggedPointer!(Storage, Tag) m_pointer; 26 27 public: 28 this(/+ std:: +/nullptr_t) 29 { 30 this.m_pointer = typeof(this.m_pointer)(null, Tag.Const); 31 } 32 33 this(const(void)* pointer, qsizetype alignment) 34 { 35 this.m_pointer = typeof(this.m_pointer)(reinterpret_cast!(Storage*)(const_cast!(void*)(pointer)), Tag.Const); 36 37 /+ Q_UNUSED(alignment) +/ 38 (mixin(Q_ASSERT(q{alignment > qsizetype(Storage.alignof)}))); 39 } 40 41 this(void* pointer, qsizetype alignment) 42 { 43 this.m_pointer = typeof(this.m_pointer)(reinterpret_cast!(Storage*)(pointer), Tag.Mutable); 44 45 /+ Q_UNUSED(alignment) +/ 46 (mixin(Q_ASSERT(q{alignment > qsizetype(Storage.alignof)}))); 47 } 48 49 /+ template<typename InputType> +/ 50 this(InputType)(const(InputType)* pointer) 51 { 52 this.m_pointer = typeof(this.m_pointer)(reinterpret_cast!(Storage*)(const_cast!(InputType*)(pointer)), Tag.Const); 53 54 static assert(InputType.alignof >= Storage.alignof); 55 } 56 57 /+ template<typename InputType> +/ 58 this(InputType)(InputType* pointer) 59 { 60 this.m_pointer = typeof(this.m_pointer)(reinterpret_cast!(Storage*)(pointer), Tag.Mutable); 61 62 static assert(InputType.alignof >= Storage.alignof); 63 } 64 65 /+ QConstPreservingPointer() = default; +/ 66 67 final const(Type)* constPointer() const 68 { 69 return reinterpret_cast!(const(Type)*)(m_pointer.data()); 70 } 71 72 final Type* mutablePointer() const 73 { 74 return m_pointer.tag() == Tag.Mutable ? reinterpret_cast!(Type*)(m_pointer.data()) : null; 75 } 76 } 77 } 78 79 /// Binding for C++ class [QTaggedIterator](https://doc.qt.io/qt-6/qtaggediterator.html). 80 extern(C++, class) struct QTaggedIterator(Iterator, IteratorCategory) 81 { 82 public Iterator base0; 83 alias base0 this; 84 public: 85 alias iterator_category = IteratorCategory; 86 /+ QTaggedIterator(Iterator &&it) : Iterator(std::move(it)) 87 { 88 const QMetaContainer metaContainer = this->metaContainer(); 89 if (std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory> 90 && !metaContainer.hasRandomAccessIterator()) { 91 qFatal("You cannot use this iterator as a random access iterator"); 92 this->clearIterator(); 93 } 94 95 if (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory> 96 && !metaContainer.hasBidirectionalIterator()) { 97 qFatal("You cannot use this iterator as a bidirectional iterator"); 98 this->clearIterator(); 99 } 100 101 if (std::is_base_of_v<std::forward_iterator_tag, IteratorCategory> 102 && !metaContainer.hasForwardIterator()) { 103 qFatal("You cannot use this iterator as a forward iterator"); 104 this->clearIterator(); 105 } 106 107 if (std::is_base_of_v<std::input_iterator_tag, IteratorCategory> 108 && !metaContainer.hasInputIterator()) { 109 qFatal("You cannot use this iterator as an input iterator"); 110 this->clearIterator(); 111 } 112 } +/ 113 114 /+bool operator ==(ref const(QTaggedIterator) o) const { return Iterator.operator==(o); }+/ 115 /+bool operator !=(ref const(QTaggedIterator) o) const { return Iterator.operator!=(o); }+/ 116 ref QTaggedIterator opUnary(string op)() if(op == "++") { Iterator.operator++(); return this; } 117 /+QTaggedIterator operator ++(int x) { return QTaggedIterator(Iterator.operator++(x)); }+//+ ; +/ 118 ref QTaggedIterator opUnary(string op)() if(op == "--") { Iterator.operator--(); return this; } 119 /+QTaggedIterator operator --(int x) { return QTaggedIterator(Iterator.operator--(x)); }+//+ ; +/ 120 ref QTaggedIterator opOpAssign(string op)(qsizetype j) if(op == "+") { Iterator.operator+=(j); return this; } 121 ref QTaggedIterator opOpAssign(string op)(qsizetype j) if(op == "-") { Iterator.operator-=(j); return this; } 122 QTaggedIterator opBinary(string op)(qsizetype j) const if(op == "+") { return QTaggedIterator(Iterator.operator+(j)); } 123 QTaggedIterator opBinary(string op)(qsizetype j) const if(op == "-") { return QTaggedIterator(Iterator.operator-(j)); } 124 qsizetype opBinary(string op)(ref const(QTaggedIterator) j) const if(op == "-") { return Iterator.operator-(j); } 125 126 /+bool operator <(ref const(QTaggedIterator) j) { return operator-(j) < 0; }+/ 127 /+bool operator >=(ref const(QTaggedIterator) j) { return !operator<(j); }+/ 128 /+bool operator >(ref const(QTaggedIterator) j) { return operator-(j) > 0; }+/ 129 /+bool operator <=(ref const(QTaggedIterator) j) { return !operator>(j); }+/ 130 131 /+ friend inline QTaggedIterator operator+(qsizetype j, const QTaggedIterator &k) { return k + j; } +/ 132 } 133 134 135 /// Binding for C++ class [QBaseIterator](https://doc.qt.io/qt-6/qbaseiterator.html). 136 class QBaseIterator(Container) 137 { 138 private: 139 ValueClass!(/+ QtPrivate:: +/QConstPreservingPointer!(ValueClass!(QIterable!(Container)))) m_iterable; 140 void* m_iterator = null; 141 142 protected: 143 /+ QBaseIterator() = default; +/ 144 this(const(QIterable!(Container)) iterable, void* iterator) 145 { 146 this.m_iterable = iterable; 147 this.m_iterator = iterator; 148 } 149 150 this(QIterable!(Container) iterable, void* iterator) 151 { 152 this.m_iterable = iterable; 153 this.m_iterator = iterator; 154 } 155 156 /+ QBaseIterator(QBaseIterator &&other) 157 : m_iterable(std::move(other.m_iterable)), m_iterator(std::move(other.m_iterator)) 158 { 159 other.m_iterator = nullptr; 160 } +/ 161 162 /+this(ref const(ValueClass!(QBaseIterator)) other) 163 { 164 this.m_iterable = other.m_iterable; 165 166 initIterator(other.m_iterator); 167 }+/ 168 169 ~this() { clearIterator(); } 170 171 /+ QBaseIterator &operator=(QBaseIterator &&other) 172 { 173 if (this != &other) { 174 clearIterator(); 175 m_iterable = std::move(other.m_iterable); 176 m_iterator = std::move(other.m_iterator); 177 other.m_iterator = nullptr; 178 } 179 return *this; 180 } +/ 181 182 /+final ref ValueClass!(QBaseIterator) operator =(ref const(ValueClass!(QBaseIterator)) other) 183 { 184 if (this != &other) { 185 clearIterator(); 186 m_iterable = other.m_iterable; 187 initIterator(other.m_iterator); 188 } 189 return *this; 190 }+/ 191 192 final QIterable!(Container) mutableIterable() const 193 { 194 return m_iterable.mutablePointer(); 195 } 196 197 final const(QIterable!(Container)) constIterable() const 198 { 199 return m_iterable.constPointer(); 200 } 201 202 /+ final void initIterator(const(void)* copy) 203 { 204 if (!copy) 205 return; 206 if (auto* mutableIt = mutableIterable()) { 207 m_iterator = metaContainer().begin(mutableIt.mutableIterable()); 208 metaContainer().copyIterator(m_iterator, copy); 209 } else if (auto* constIt = constIterable()) { 210 m_iterator = metaContainer().constBegin(constIt.constIterable()); 211 metaContainer().copyConstIterator(m_iterator, copy); 212 } 213 }+/ 214 215 final void clearIterator() 216 { 217 if (!m_iterator) 218 return; 219 if (mutableIterable()) 220 metaContainer().destroyIterator(m_iterator); 221 else 222 metaContainer().destroyConstIterator(m_iterator); 223 } 224 225 public: 226 final void* mutableIterator() { return m_iterator; } 227 final const(void)* constIterator() const { return m_iterator; } 228 final Container metaContainer() const { return constIterable().m_metaContainer; } 229 } 230 231 struct QIterator(Container) 232 { 233 public QBaseIterator!(Container) base0; 234 alias base0 this; 235 public: 236 alias difference_type = qsizetype; 237 238 /+ explicit +/this(QIterable!(Container) iterable, void* iterator) 239 { 240 this.QBaseIterator!(Container) = typeof(this.QBaseIterator!(Container))(iterable, iterator); 241 242 (mixin(Q_ASSERT(q{iterable !is null}))); 243 } 244 245 /+bool operator ==(ref const(QIterator) o) const 246 { 247 return this.metaContainer().compareIterator(this.constIterator(), o.constIterator()); 248 }+/ 249 250 /+bool operator !=(ref const(QIterator) o) const 251 { 252 return !this.metaContainer().compareIterator(this.constIterator(), o.constIterator()); 253 }+/ 254 255 ref QIterator opUnary(string op)() if(op == "++") 256 { 257 this.metaContainer().advanceIterator(this.mutableIterator(), 1); 258 return this; 259 } 260 261 /+QIterator operator ++(int) 262 { 263 QIterable!(Container) iterable = this.mutableIterable(); 264 const(Container) metaContainer = this.metaContainer(); 265 auto result = QIterator(iterable, metaContainer.begin(iterable.mutableIterable())); 266 metaContainer.copyIterator(result.mutableIterator(), this.constIterator()); 267 metaContainer.advanceIterator(this.mutableIterator(), 1); 268 return result; 269 }+/ 270 271 ref QIterator opUnary(string op)() if(op == "--") 272 { 273 this.metaContainer().advanceIterator(this.mutableIterator(), -1); 274 return this; 275 } 276 277 /+QIterator operator --(int) 278 { 279 QIterable!(Container) iterable = this.mutableIterable(); 280 const(Container) metaContainer = this.metaContainer(); 281 auto result = QIterator(iterable, metaContainer.begin(iterable.mutableIterable())); 282 metaContainer.copyIterator(result.mutableIterator(), this.constIterator()); 283 metaContainer.advanceIterator(this.mutableIterator(), -1); 284 return result; 285 }+/ 286 287 ref QIterator opOpAssign(string op)(qsizetype j) if(op == "+") 288 { 289 this.metaContainer().advanceIterator(this.mutableIterator(), j); 290 return this; 291 } 292 293 ref QIterator opOpAssign(string op)(qsizetype j) if(op == "-") 294 { 295 this.metaContainer().advanceIterator(this.mutableIterator(), -j); 296 return this; 297 } 298 299 QIterator opBinary(string op)(qsizetype j) const if(op == "+") 300 { 301 QIterable!(Container) iterable = this.mutableIterable(); 302 const(Container) metaContainer = this.metaContainer(); 303 auto result = QIterator(iterable, metaContainer.begin(iterable.mutableIterable())); 304 metaContainer.copyIterator(result.mutableIterator(), this.constIterator()); 305 metaContainer.advanceIterator(result.mutableIterator(), j); 306 return result; 307 } 308 309 QIterator opBinary(string op)(qsizetype j) const if(op == "-") 310 { 311 QIterable!(Container) iterable = this.mutableIterable(); 312 const(Container) metaContainer = this.metaContainer(); 313 auto result = QIterator(iterable, metaContainer.begin(iterable.mutableIterable())); 314 metaContainer.copyIterator(result.mutableIterator(), this.constIterator()); 315 metaContainer.advanceIterator(result.mutableIterator(), -j); 316 return result; 317 } 318 319 qsizetype opBinary(string op)(ref const(QIterator) j) const if(op == "-") 320 { 321 return this.metaContainer().diffIterator(this.constIterator(), j.constIterator()); 322 } 323 324 /+ friend inline QIterator operator+(qsizetype j, const QIterator &k) { return k + j; } +/ 325 } 326 327 struct QConstIterator(Container) 328 { 329 public QBaseIterator!(Container) base0; 330 alias base0 this; 331 public: 332 alias difference_type = qsizetype; 333 334 /+ explicit +/this(const(QIterable!(Container)) iterable, void* iterator) 335 { 336 this.QBaseIterator!(Container) = typeof(this.QBaseIterator!(Container))(iterable, iterator); 337 } 338 339 /+bool operator ==(ref const(QConstIterator) o) const 340 { 341 return this.metaContainer().compareConstIterator( 342 this.constIterator(), o.constIterator()); 343 }+/ 344 345 /+bool operator !=(ref const(QConstIterator) o) const 346 { 347 return !this.metaContainer().compareConstIterator( 348 this.constIterator(), o.constIterator()); 349 }+/ 350 351 ref QConstIterator opUnary(string op)() if(op == "++") 352 { 353 this.metaContainer().advanceConstIterator(this.mutableIterator(), 1); 354 return this; 355 } 356 357 /+QConstIterator operator ++(int) 358 { 359 const(Container) metaContainer = this.metaContainer(); 360 auto result = QConstIterator(this.constIterable(), metaContainer.constBegin( 361 this.constIterable().constIterable())); 362 metaContainer.copyConstIterator(result.mutableIterator(), this.constIterator()); 363 metaContainer.advanceConstIterator(this.mutableIterator(), 1); 364 return result; 365 }+/ 366 367 ref QConstIterator opUnary(string op)() if(op == "--") 368 { 369 this.metaContainer().advanceConstIterator(this.mutableIterator(), -1); 370 return this; 371 } 372 373 /+QConstIterator operator --(int) 374 { 375 const(Container) metaContainer = this.metaContainer(); 376 auto result = QConstIterator(this.constIterable(), metaContainer.constBegin( 377 this.constIterable().constIterable())); 378 metaContainer.copyConstIterator(result.mutableIterator(), this.constIterator()); 379 metaContainer.advanceConstIterator(this.mutableIterator(), -1); 380 return result; 381 }+/ 382 383 ref QConstIterator opOpAssign(string op)(qsizetype j) if(op == "+") 384 { 385 this.metaContainer().advanceConstIterator(this.mutableIterator(), j); 386 return this; 387 } 388 389 ref QConstIterator opOpAssign(string op)(qsizetype j) if(op == "-") 390 { 391 this.metaContainer().advanceConstIterator(this.mutableIterator(), -j); 392 return this; 393 } 394 395 QConstIterator opBinary(string op)(qsizetype j) const if(op == "+") 396 { 397 const(Container) metaContainer = this.metaContainer(); 398 auto result = QConstIterator( 399 this.constIterable(), 400 metaContainer.constBegin(this.constIterable().constIterable())); 401 metaContainer.copyConstIterator(result.mutableIterator(), this.constIterator()); 402 metaContainer.advanceConstIterator(result.mutableIterator(), j); 403 return result; 404 } 405 406 QConstIterator opBinary(string op)(qsizetype j) const if(op == "-") 407 { 408 const(Container) metaContainer = this.metaContainer(); 409 auto result = QConstIterator(this.constIterable(), metaContainer.constBegin( 410 this.constIterable().constIterable())); 411 metaContainer.copyConstIterator(result.mutableIterator(), this.constIterator()); 412 metaContainer.advanceConstIterator(result.mutableIterator(), -j); 413 return result; 414 } 415 416 qsizetype opBinary(string op)(ref const(QConstIterator) j) const if(op == "-") 417 { 418 return this.metaContainer().diffIterator(this.constIterator(), j.constIterator()); 419 } 420 421 /+ friend inline QConstIterator operator+(qsizetype j, const QConstIterator &k) 422 { 423 return k + j; 424 } +/ 425 } 426 427 /// Binding for C++ class [QIterable](https://doc.qt.io/qt-6/qiterable.html). 428 class QIterable(Container) 429 { 430 private: 431 /+ friend class QBaseIterator<Container>; +/ 432 433 protected: 434 uint m_revision = 0; 435 ValueClass!(/+ QtPrivate:: +/QConstPreservingPointer!(void, quint16)) m_iterable; 436 Container m_metaContainer; 437 438 public: 439 /+ template<class T> +/ 440 this(T)(ref const(Container) metaContainer, const(T)* p) 441 { 442 this.m_iterable = p; 443 this.m_metaContainer = metaContainer; 444 } 445 446 /+ template<class T> +/ 447 this(T)(ref const(Container) metaContainer, T* p) 448 { 449 this.m_iterable = p; 450 this.m_metaContainer = metaContainer; 451 } 452 453 /+ template<typename Pointer> +/ 454 this(Pointer)(ref const(Container) metaContainer, Pointer iterable) 455 { 456 this.m_iterable = iterable; 457 this.m_metaContainer = metaContainer; 458 } 459 460 this(ref const(Container) metaContainer, qsizetype alignment, const(void)* p) 461 { 462 this.m_iterable = typeof(this.m_iterable)(p, alignment); 463 this.m_metaContainer = metaContainer; 464 } 465 466 this(ref const(Container) metaContainer, qsizetype alignment, void* p) 467 { 468 this.m_iterable = typeof(this.m_iterable)(p, alignment); 469 this.m_metaContainer = metaContainer; 470 } 471 472 final bool canInputIterate() const 473 { 474 return m_metaContainer.hasInputIterator(); 475 } 476 477 final bool canForwardIterate() const 478 { 479 return m_metaContainer.hasForwardIterator(); 480 } 481 482 final bool canReverseIterate() const 483 { 484 return m_metaContainer.hasBidirectionalIterator(); 485 } 486 487 final bool canRandomAccessIterate() const 488 { 489 return m_metaContainer.hasRandomAccessIterator(); 490 } 491 492 final const(void)* constIterable() const { return m_iterable.constPointer(); } 493 final void* mutableIterable() { return m_iterable.mutablePointer(); } 494 495 final QConstIterator!(Container) constBegin() const 496 { 497 return QConstIterator(this, m_metaContainer.constBegin(constIterable())); 498 } 499 500 final QConstIterator!(Container) constEnd() const 501 { 502 return QConstIterator(this, m_metaContainer.constEnd(constIterable())); 503 } 504 505 final QIterator!(Container) mutableBegin() 506 { 507 return QIterator(this, m_metaContainer.begin(mutableIterable())); 508 } 509 510 final QIterator!(Container) mutableEnd() 511 { 512 return QIterator(this, m_metaContainer.end(mutableIterable())); 513 } 514 515 final qsizetype size() const 516 { 517 const(void)* container = constIterable(); 518 if (m_metaContainer.hasSize()) 519 return m_metaContainer.size(container); 520 if (!m_metaContainer.hasConstIterator()) 521 return -1; 522 523 const(void)* begin = m_metaContainer.constBegin(container); 524 const(void)* end = m_metaContainer.constEnd(container); 525 const(qsizetype) size = m_metaContainer.diffConstIterator(end, begin); 526 m_metaContainer.destroyConstIterator(begin); 527 m_metaContainer.destroyConstIterator(end); 528 return size; 529 } 530 531 final Container metaContainer() const 532 { 533 return m_metaContainer; 534 }/+ ; +/ 535 } 536