2 * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
4 * SPDX-License-Identifier: GPL-2.0-or-later
10 #include "dolphin_export.h"
11 #include "kitemviews/kitemrange.h"
14 * @brief Stores a set of integer numbers in a space-efficient way.
16 * This class is similar to QSet<int>, but it has the following advantages:
18 * 1. It uses less memory than a QSet<int> if many consecutive numbers are
19 * stored. This is achieved by not storing each number separately, but
20 * "ranges" of numbers.
22 * Example: The set {1, 2, 3, 4, 5} is represented by a single range which
23 * starts at 1 and has the length 5.
25 * 2. When iterating through a KItemSet using KItemSet::iterator or
26 * KItemSet::const_iterator, the numbers are traversed in ascending order.
28 * The complexity of most operations depends on the number of ranges.
31 class DOLPHIN_EXPORT KItemSet
35 KItemSet(const KItemSet
&other
);
37 KItemSet
&operator=(const KItemSet
&other
);
40 * Returns the number of items in the set.
41 * Complexity: O(log(number of ranges)).
48 bool operator==(const KItemSet
&other
) const;
49 bool operator!=(const KItemSet
&other
) const;
53 iterator(const KItemRangeList::iterator
&rangeIt
, int offset
= 0)
60 iterator(const iterator
&other
)
61 : m_rangeIt(other
.m_rangeIt
)
62 , m_offset(other
.m_offset
)
66 iterator
&operator=(const iterator
&other
)
68 m_rangeIt
= other
.m_rangeIt
;
69 m_offset
= other
.m_offset
;
73 ~iterator() = default;
77 return m_rangeIt
->index
+ m_offset
;
80 inline bool operator==(const iterator
&other
) const
82 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
85 inline bool operator!=(const iterator
&other
) const
87 return !(*this == other
);
90 inline iterator
&operator++()
94 if (m_offset
== m_rangeIt
->count
) {
102 inline iterator
operator++(int)
109 inline iterator
&operator--()
113 m_offset
= m_rangeIt
->count
- 1;
121 inline iterator
operator--(int)
129 KItemRangeList::iterator m_rangeIt
;
132 friend class const_iterator
;
133 friend class KItemSet
;
138 const_iterator(KItemRangeList::const_iterator rangeIt
, int offset
= 0)
145 const_iterator(const const_iterator
&other
)
146 : m_rangeIt(other
.m_rangeIt
)
147 , m_offset(other
.m_offset
)
151 explicit const_iterator(const iterator
&other
)
152 : m_rangeIt(other
.m_rangeIt
)
153 , m_offset(other
.m_offset
)
157 const_iterator
&operator=(const const_iterator
&other
)
159 m_rangeIt
= other
.m_rangeIt
;
160 m_offset
= other
.m_offset
;
164 ~const_iterator() = default;
166 int operator*() const
168 return m_rangeIt
->index
+ m_offset
;
171 inline bool operator==(const const_iterator
&other
) const
173 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
176 inline bool operator!=(const const_iterator
&other
) const
178 return !(*this == other
);
181 inline const_iterator
&operator++()
185 if (m_offset
== m_rangeIt
->count
) {
193 inline const_iterator
operator++(int)
195 const_iterator r
= *this;
200 inline const_iterator
&operator--()
204 m_offset
= m_rangeIt
->count
- 1;
212 inline const_iterator
operator--(int)
214 const_iterator r
= *this;
220 KItemRangeList::const_iterator m_rangeIt
;
223 friend class KItemSet
;
226 class const_reverse_iterator
229 const_reverse_iterator(KItemSet::const_iterator rangeIt
)
234 const_reverse_iterator(const KItemSet::const_reverse_iterator
&other
)
235 : m_current(other
.base())
239 int operator*() const
241 // analog to std::prev
242 auto t
= const_iterator(m_current
);
247 inline bool operator==(const const_reverse_iterator
&other
) const
249 return m_current
== other
.m_current
;
252 bool operator!=(const const_reverse_iterator
&other
) const
254 return !(*this == other
);
257 const_reverse_iterator
&operator++()
262 const_reverse_iterator
operator++(int)
269 const_reverse_iterator
&operator--()
274 const_reverse_iterator
operator--(int)
281 KItemSet::const_iterator
base() const
287 KItemSet::const_iterator m_current
;
291 const_iterator
begin() const;
292 const_iterator
constBegin() const;
294 const_iterator
end() const;
295 const_iterator
constEnd() const;
297 const_reverse_iterator
rend() const;
298 const_reverse_iterator
rbegin() const;
303 bool contains(int i
) const;
304 iterator
insert(int i
);
305 iterator
find(int i
);
306 const_iterator
constFind(int i
) const;
308 iterator
erase(iterator it
);
311 * Returns a new set which contains all items that are contained in this
312 * KItemSet, in \a other, or in both.
314 KItemSet
operator+(const KItemSet
&other
) const;
317 * Returns a new set which contains all items that are contained either in
318 * this KItemSet, or in \a other, but not in both (the symmetric difference
319 * of both KItemSets).
321 KItemSet
operator^(const KItemSet
&other
) const;
323 KItemSet
&operator<<(int i
);
327 * Returns true if the KItemSet is valid, and false otherwise.
328 * A valid KItemSet must store the item ranges in ascending order, and
329 * the ranges must not overlap.
331 bool isValid() const;
334 * This function returns an iterator that points to the KItemRange which
335 * contains i, or m_itemRanges.end() if no such range exists.
337 KItemRangeList::iterator
rangeForItem(int i
);
340 * This function returns an iterator that points to the KItemRange which
341 * contains i, or m_itemRanges.constEnd() if no such range exists.
343 KItemRangeList::const_iterator
constRangeForItem(int i
) const;
345 KItemRangeList m_itemRanges
;
347 friend class KItemSetTest
;
350 inline KItemSet::KItemSet()
355 inline KItemSet::KItemSet(const KItemSet
&other
)
356 : m_itemRanges(other
.m_itemRanges
)
360 inline KItemSet::~KItemSet() = default;
362 inline KItemSet
&KItemSet::operator=(const KItemSet
&other
)
364 m_itemRanges
= other
.m_itemRanges
;
368 inline int KItemSet::count() const
371 for (const KItemRange
&range
: std::as_const(m_itemRanges
)) {
372 result
+= range
.count
;
377 inline bool KItemSet::isEmpty() const
379 return m_itemRanges
.isEmpty();
382 inline void KItemSet::clear()
384 m_itemRanges
.clear();
387 inline bool KItemSet::operator==(const KItemSet
&other
) const
389 return m_itemRanges
== other
.m_itemRanges
;
392 inline bool KItemSet::operator!=(const KItemSet
&other
) const
394 return m_itemRanges
!= other
.m_itemRanges
;
397 inline bool KItemSet::contains(int i
) const
399 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
400 return it
!= m_itemRanges
.end();
403 inline KItemSet::iterator
KItemSet::find(int i
)
405 const KItemRangeList::iterator it
= rangeForItem(i
);
406 if (it
!= m_itemRanges
.end()) {
407 return iterator(it
, i
- it
->index
);
413 inline KItemSet::const_iterator
KItemSet::constFind(int i
) const
415 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
416 if (it
!= m_itemRanges
.constEnd()) {
417 return const_iterator(it
, i
- it
->index
);
423 inline bool KItemSet::remove(int i
)
425 iterator it
= find(i
);
434 inline KItemSet::iterator
KItemSet::begin()
436 return iterator(m_itemRanges
.begin());
439 inline KItemSet::const_iterator
KItemSet::begin() const
441 return const_iterator(m_itemRanges
.begin());
444 inline KItemSet::const_iterator
KItemSet::constBegin() const
446 return const_iterator(m_itemRanges
.constBegin());
449 inline KItemSet::iterator
KItemSet::end()
451 return iterator(m_itemRanges
.end());
454 inline KItemSet::const_iterator
KItemSet::end() const
456 return const_iterator(m_itemRanges
.end());
459 inline KItemSet::const_iterator
KItemSet::constEnd() const
461 return const_iterator(m_itemRanges
.constEnd());
464 inline int KItemSet::first() const
466 return m_itemRanges
.first().index
;
469 inline int KItemSet::last() const
471 const KItemRange
&lastRange
= m_itemRanges
.last();
472 return lastRange
.index
+ lastRange
.count
- 1;
475 inline KItemSet::const_reverse_iterator
KItemSet::rend() const
477 return KItemSet::const_reverse_iterator(constBegin());
480 inline KItemSet::const_reverse_iterator
KItemSet::rbegin() const
482 return KItemSet::const_reverse_iterator(constEnd());
485 inline KItemSet
&KItemSet::operator<<(int i
)