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