2 * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
4 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include "dolphin_export.h"
12 #include "kitemviews/kitemrange.h"
15 * @brief Stores a set of integer numbers in a space-efficient way.
17 * This class is similar to QSet<int>, but it has the following advantages:
19 * 1. It uses less memory than a QSet<int> if many consecutive numbers are
20 * stored. This is achieved by not storing each number separately, but
21 * "ranges" of numbers.
23 * Example: The set {1, 2, 3, 4, 5} is represented by a single range which
24 * starts at 1 and has the length 5.
26 * 2. When iterating through a KItemSet using KItemSet::iterator or
27 * KItemSet::const_iterator, the numbers are traversed in ascending order.
29 * The complexity of most operations depends on the number of ranges.
32 class DOLPHIN_EXPORT KItemSet
36 KItemSet(const KItemSet
& other
);
38 KItemSet
& operator=(const KItemSet
& other
);
41 * Returns the number of items in the set.
42 * Complexity: O(log(number of ranges)).
49 bool operator==(const KItemSet
& other
) const;
50 bool operator!=(const KItemSet
& other
) const;
54 iterator(const KItemRangeList::iterator
& rangeIt
, int offset
) :
61 iterator(const iterator
& other
) :
62 m_rangeIt(other
.m_rangeIt
),
63 m_offset(other
.m_offset
)
67 iterator
& operator=(const iterator
& other
)
69 m_rangeIt
= other
.m_rangeIt
;
70 m_offset
= other
.m_offset
;
74 ~iterator() = default;
78 return m_rangeIt
->index
+ m_offset
;
81 inline bool operator==(const iterator
& other
) const
83 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
86 inline bool operator!=(const iterator
& other
) const
88 return !(*this == other
);
91 inline iterator
& operator++()
95 if (m_offset
== m_rangeIt
->count
) {
103 inline iterator
operator++(int)
110 inline iterator
& operator--()
114 m_offset
= m_rangeIt
->count
- 1;
122 inline iterator
operator--(int)
130 KItemRangeList::iterator m_rangeIt
;
133 friend class const_iterator
;
134 friend class KItemSet
;
140 const_iterator(KItemRangeList::const_iterator rangeIt
, int offset
) :
147 const_iterator(const const_iterator
& other
) :
148 m_rangeIt(other
.m_rangeIt
),
149 m_offset(other
.m_offset
)
153 explicit const_iterator(const iterator
& other
) :
154 m_rangeIt(other
.m_rangeIt
),
155 m_offset(other
.m_offset
)
159 const_iterator
& operator=(const const_iterator
& other
)
161 m_rangeIt
= other
.m_rangeIt
;
162 m_offset
= other
.m_offset
;
166 ~const_iterator() = default;
168 int operator*() const
170 return m_rangeIt
->index
+ m_offset
;
173 inline bool operator==(const const_iterator
& other
) const
175 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
178 inline bool operator!=(const const_iterator
& other
) const
180 return !(*this == other
);
183 inline const_iterator
& operator++()
187 if (m_offset
== m_rangeIt
->count
) {
195 inline const_iterator
operator++(int)
197 const_iterator r
= *this;
202 inline const_iterator
& operator--()
206 m_offset
= m_rangeIt
->count
- 1;
214 inline const_iterator
operator--(int)
216 const_iterator r
= *this;
222 KItemRangeList::const_iterator m_rangeIt
;
225 friend class KItemSet
;
229 const_iterator
begin() const;
230 const_iterator
constBegin() const;
232 const_iterator
end() const;
233 const_iterator
constEnd() const;
238 bool contains(int i
) const;
239 iterator
insert(int i
);
240 iterator
find(int i
);
241 const_iterator
constFind(int i
) const;
243 iterator
erase(iterator it
);
246 * Returns a new set which contains all items that are contained in this
247 * KItemSet, in \a other, or in both.
249 KItemSet
operator+(const KItemSet
& other
) const;
252 * Returns a new set which contains all items that are contained either in
253 * this KItemSet, or in \a other, but not in both (the symmetric difference
254 * of both KItemSets).
256 KItemSet
operator^(const KItemSet
& other
) const;
258 KItemSet
& operator<<(int i
);
262 * Returns true if the KItemSet is valid, and false otherwise.
263 * A valid KItemSet must store the item ranges in ascending order, and
264 * the ranges must not overlap.
266 bool isValid() const;
269 * This function returns an iterator that points to the KItemRange which
270 * contains i, or m_itemRanges.end() if no such range exists.
272 KItemRangeList::iterator
rangeForItem(int i
);
275 * This function returns an iterator that points to the KItemRange which
276 * contains i, or m_itemRanges.constEnd() if no such range exists.
278 KItemRangeList::const_iterator
constRangeForItem(int i
) const;
280 KItemRangeList m_itemRanges
;
282 friend class KItemSetTest
;
285 inline KItemSet::KItemSet() :
290 inline KItemSet::KItemSet(const KItemSet
& other
) :
291 m_itemRanges(other
.m_itemRanges
)
295 inline KItemSet::~KItemSet() = default;
297 inline KItemSet
& KItemSet::operator=(const KItemSet
& other
)
299 m_itemRanges
=other
.m_itemRanges
;
303 inline int KItemSet::count() const
306 for (const KItemRange
& range
: qAsConst(m_itemRanges
)) {
307 result
+= range
.count
;
312 inline bool KItemSet::isEmpty() const
314 return m_itemRanges
.isEmpty();
317 inline void KItemSet::clear()
319 m_itemRanges
.clear();
322 inline bool KItemSet::operator==(const KItemSet
& other
) const
324 return m_itemRanges
== other
.m_itemRanges
;
327 inline bool KItemSet::operator!=(const KItemSet
& other
) const
329 return m_itemRanges
!= other
.m_itemRanges
;
332 inline bool KItemSet::contains(int i
) const
334 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
335 return it
!= m_itemRanges
.end();
338 inline KItemSet::iterator
KItemSet::find(int i
)
340 const KItemRangeList::iterator it
= rangeForItem(i
);
341 if (it
!= m_itemRanges
.end()) {
342 return iterator(it
, i
- it
->index
);
348 inline KItemSet::const_iterator
KItemSet::constFind(int i
) const
350 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
351 if (it
!= m_itemRanges
.constEnd()) {
352 return const_iterator(it
, i
- it
->index
);
358 inline bool KItemSet::remove(int i
)
360 iterator it
= find(i
);
369 inline KItemSet::iterator
KItemSet::begin()
371 return iterator(m_itemRanges
.begin(), 0);
374 inline KItemSet::const_iterator
KItemSet::begin() const
376 return const_iterator(m_itemRanges
.begin(), 0);
379 inline KItemSet::const_iterator
KItemSet::constBegin() const
381 return const_iterator(m_itemRanges
.constBegin(), 0);
384 inline KItemSet::iterator
KItemSet::end()
386 return iterator(m_itemRanges
.end(), 0);
389 inline KItemSet::const_iterator
KItemSet::end() const
391 return const_iterator(m_itemRanges
.end(), 0);
394 inline KItemSet::const_iterator
KItemSet::constEnd() const
396 return const_iterator(m_itemRanges
.constEnd(), 0);
399 inline int KItemSet::first() const
401 return m_itemRanges
.first().index
;
404 inline int KItemSet::last() const
406 const KItemRange
& lastRange
= m_itemRanges
.last();
407 return lastRange
.index
+ lastRange
.count
- 1;
410 inline KItemSet
& KItemSet::operator<<(int i
)