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
)
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
)
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
;
227 const_iterator
begin() const;
228 const_iterator
constBegin() const;
230 const_iterator
end() const;
231 const_iterator
constEnd() const;
236 bool contains(int i
) const;
237 iterator
insert(int i
);
238 iterator
find(int i
);
239 const_iterator
constFind(int i
) const;
241 iterator
erase(iterator it
);
244 * Returns a new set which contains all items that are contained in this
245 * KItemSet, in \a other, or in both.
247 KItemSet
operator+(const KItemSet
&other
) const;
250 * Returns a new set which contains all items that are contained either in
251 * this KItemSet, or in \a other, but not in both (the symmetric difference
252 * of both KItemSets).
254 KItemSet
operator^(const KItemSet
&other
) const;
256 KItemSet
&operator<<(int i
);
260 * Returns true if the KItemSet is valid, and false otherwise.
261 * A valid KItemSet must store the item ranges in ascending order, and
262 * the ranges must not overlap.
264 bool isValid() const;
267 * This function returns an iterator that points to the KItemRange which
268 * contains i, or m_itemRanges.end() if no such range exists.
270 KItemRangeList::iterator
rangeForItem(int i
);
273 * This function returns an iterator that points to the KItemRange which
274 * contains i, or m_itemRanges.constEnd() if no such range exists.
276 KItemRangeList::const_iterator
constRangeForItem(int i
) const;
278 KItemRangeList m_itemRanges
;
280 friend class KItemSetTest
;
283 inline KItemSet::KItemSet()
288 inline KItemSet::KItemSet(const KItemSet
&other
)
289 : m_itemRanges(other
.m_itemRanges
)
293 inline KItemSet::~KItemSet() = default;
295 inline KItemSet
&KItemSet::operator=(const KItemSet
&other
)
297 m_itemRanges
= other
.m_itemRanges
;
301 inline int KItemSet::count() const
304 for (const KItemRange
&range
: qAsConst(m_itemRanges
)) {
305 result
+= range
.count
;
310 inline bool KItemSet::isEmpty() const
312 return m_itemRanges
.isEmpty();
315 inline void KItemSet::clear()
317 m_itemRanges
.clear();
320 inline bool KItemSet::operator==(const KItemSet
&other
) const
322 return m_itemRanges
== other
.m_itemRanges
;
325 inline bool KItemSet::operator!=(const KItemSet
&other
) const
327 return m_itemRanges
!= other
.m_itemRanges
;
330 inline bool KItemSet::contains(int i
) const
332 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
333 return it
!= m_itemRanges
.end();
336 inline KItemSet::iterator
KItemSet::find(int i
)
338 const KItemRangeList::iterator it
= rangeForItem(i
);
339 if (it
!= m_itemRanges
.end()) {
340 return iterator(it
, i
- it
->index
);
346 inline KItemSet::const_iterator
KItemSet::constFind(int i
) const
348 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
349 if (it
!= m_itemRanges
.constEnd()) {
350 return const_iterator(it
, i
- it
->index
);
356 inline bool KItemSet::remove(int i
)
358 iterator it
= find(i
);
367 inline KItemSet::iterator
KItemSet::begin()
369 return iterator(m_itemRanges
.begin(), 0);
372 inline KItemSet::const_iterator
KItemSet::begin() const
374 return const_iterator(m_itemRanges
.begin(), 0);
377 inline KItemSet::const_iterator
KItemSet::constBegin() const
379 return const_iterator(m_itemRanges
.constBegin(), 0);
382 inline KItemSet::iterator
KItemSet::end()
384 return iterator(m_itemRanges
.end(), 0);
387 inline KItemSet::const_iterator
KItemSet::end() const
389 return const_iterator(m_itemRanges
.end(), 0);
392 inline KItemSet::const_iterator
KItemSet::constEnd() const
394 return const_iterator(m_itemRanges
.constEnd(), 0);
397 inline int KItemSet::first() const
399 return m_itemRanges
.first().index
;
402 inline int KItemSet::last() const
404 const KItemRange
&lastRange
= m_itemRanges
.last();
405 return lastRange
.index
+ lastRange
.count
- 1;
408 inline KItemSet
&KItemSet::operator<<(int i
)