1 /***************************************************************************
2 * Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
23 #include "dolphin_export.h"
24 #include "kitemviews/kitemrange.h"
27 * @brief Stores a set of integer numbers in a space-efficient way.
29 * This class is similar to QSet<int>, but it has the following advantages:
31 * 1. It uses less memory than a QSet<int> if many consecutive numbers are
32 * stored. This is achieved by not storing each number separately, but
33 * "ranges" of numbers.
35 * Example: The set {1, 2, 3, 4, 5} is represented by a single range which
36 * starts at 1 and has the length 5.
38 * 2. When iterating through a KItemSet using KItemSet::iterator or
39 * KItemSet::const_iterator, the numbers are traversed in ascending order.
41 * The complexity of most operations depends on the number of ranges.
44 class DOLPHIN_EXPORT KItemSet
48 KItemSet(const KItemSet
& other
);
50 KItemSet
& operator=(const KItemSet
& other
);
53 * Returns the number of items in the set.
54 * Complexity: O(log(number of ranges)).
61 bool operator==(const KItemSet
& other
) const;
62 bool operator!=(const KItemSet
& other
) const;
66 iterator(const KItemRangeList::iterator
& rangeIt
, int offset
) :
73 iterator(const iterator
& other
) :
74 m_rangeIt(other
.m_rangeIt
),
75 m_offset(other
.m_offset
)
79 iterator
& operator=(const iterator
& other
)
81 m_rangeIt
= other
.m_rangeIt
;
82 m_offset
= other
.m_offset
;
86 ~iterator() = default;
90 return m_rangeIt
->index
+ m_offset
;
93 inline bool operator==(const iterator
& other
) const
95 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
98 inline bool operator!=(const iterator
& other
) const
100 return !(*this == other
);
103 inline iterator
& operator++()
107 if (m_offset
== m_rangeIt
->count
) {
115 inline iterator
operator++(int)
122 inline iterator
& operator--()
126 m_offset
= m_rangeIt
->count
- 1;
134 inline iterator
operator--(int)
142 KItemRangeList::iterator m_rangeIt
;
145 friend class const_iterator
;
146 friend class KItemSet
;
152 const_iterator(KItemRangeList::const_iterator rangeIt
, int offset
) :
159 const_iterator(const const_iterator
& other
) :
160 m_rangeIt(other
.m_rangeIt
),
161 m_offset(other
.m_offset
)
165 explicit const_iterator(const iterator
& other
) :
166 m_rangeIt(other
.m_rangeIt
),
167 m_offset(other
.m_offset
)
171 const_iterator
& operator=(const const_iterator
& other
)
173 m_rangeIt
= other
.m_rangeIt
;
174 m_offset
= other
.m_offset
;
178 ~const_iterator() = default;
180 int operator*() const
182 return m_rangeIt
->index
+ m_offset
;
185 inline bool operator==(const const_iterator
& other
) const
187 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
190 inline bool operator!=(const const_iterator
& other
) const
192 return !(*this == other
);
195 inline const_iterator
& operator++()
199 if (m_offset
== m_rangeIt
->count
) {
207 inline const_iterator
operator++(int)
209 const_iterator r
= *this;
214 inline const_iterator
& operator--()
218 m_offset
= m_rangeIt
->count
- 1;
226 inline const_iterator
operator--(int)
228 const_iterator r
= *this;
234 KItemRangeList::const_iterator m_rangeIt
;
237 friend class KItemSet
;
241 const_iterator
begin() const;
242 const_iterator
constBegin() const;
244 const_iterator
end() const;
245 const_iterator
constEnd() const;
250 bool contains(int i
) const;
251 iterator
insert(int i
);
252 iterator
find(int i
);
253 const_iterator
constFind(int i
) const;
255 iterator
erase(iterator it
);
258 * Returns a new set which contains all items that are contained in this
259 * KItemSet, in \a other, or in both.
261 KItemSet
operator+(const KItemSet
& other
) const;
264 * Returns a new set which contains all items that are contained either in
265 * this KItemSet, or in \a other, but not in both (the symmetric difference
266 * of both KItemSets).
268 KItemSet
operator^(const KItemSet
& other
) const;
270 KItemSet
& operator<<(int i
);
274 * Returns true if the KItemSet is valid, and false otherwise.
275 * A valid KItemSet must store the item ranges in ascending order, and
276 * the ranges must not overlap.
278 bool isValid() const;
281 * This function returns an iterator that points to the KItemRange which
282 * contains i, or m_itemRanges.end() if no such range exists.
284 KItemRangeList::iterator
rangeForItem(int i
);
287 * This function returns an iterator that points to the KItemRange which
288 * contains i, or m_itemRanges.constEnd() if no such range exists.
290 KItemRangeList::const_iterator
constRangeForItem(int i
) const;
292 KItemRangeList m_itemRanges
;
294 friend class KItemSetTest
;
297 inline KItemSet::KItemSet() :
302 inline KItemSet::KItemSet(const KItemSet
& other
) :
303 m_itemRanges(other
.m_itemRanges
)
307 inline KItemSet::~KItemSet() = default;
309 inline KItemSet
& KItemSet::operator=(const KItemSet
& other
)
311 m_itemRanges
=other
.m_itemRanges
;
315 inline int KItemSet::count() const
318 foreach (const KItemRange
& range
, m_itemRanges
) {
319 result
+= range
.count
;
324 inline bool KItemSet::isEmpty() const
326 return m_itemRanges
.isEmpty();
329 inline void KItemSet::clear()
331 m_itemRanges
.clear();
334 inline bool KItemSet::operator==(const KItemSet
& other
) const
336 return m_itemRanges
== other
.m_itemRanges
;
339 inline bool KItemSet::operator!=(const KItemSet
& other
) const
341 return m_itemRanges
!= other
.m_itemRanges
;
344 inline bool KItemSet::contains(int i
) const
346 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
347 return it
!= m_itemRanges
.end();
350 inline KItemSet::iterator
KItemSet::find(int i
)
352 const KItemRangeList::iterator it
= rangeForItem(i
);
353 if (it
!= m_itemRanges
.end()) {
354 return iterator(it
, i
- it
->index
);
360 inline KItemSet::const_iterator
KItemSet::constFind(int i
) const
362 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
363 if (it
!= m_itemRanges
.constEnd()) {
364 return const_iterator(it
, i
- it
->index
);
370 inline bool KItemSet::remove(int i
)
372 iterator it
= find(i
);
381 inline KItemSet::iterator
KItemSet::begin()
383 return iterator(m_itemRanges
.begin(), 0);
386 inline KItemSet::const_iterator
KItemSet::begin() const
388 return const_iterator(m_itemRanges
.begin(), 0);
391 inline KItemSet::const_iterator
KItemSet::constBegin() const
393 return const_iterator(m_itemRanges
.constBegin(), 0);
396 inline KItemSet::iterator
KItemSet::end()
398 return iterator(m_itemRanges
.end(), 0);
401 inline KItemSet::const_iterator
KItemSet::end() const
403 return const_iterator(m_itemRanges
.end(), 0);
406 inline KItemSet::const_iterator
KItemSet::constEnd() const
408 return const_iterator(m_itemRanges
.constEnd(), 0);
411 inline int KItemSet::first() const
413 return m_itemRanges
.first().index
;
416 inline int KItemSet::last() const
418 const KItemRange
& lastRange
= m_itemRanges
.last();
419 return lastRange
.index
+ lastRange
.count
- 1;
422 inline KItemSet
& KItemSet::operator<<(int i
)