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 <kitemviews/kitemrange.h>
26 * @brief Stores a set of integer numbers in a space-efficient way.
28 * This class is similar to QSet<int>, but it has the following advantages:
30 * 1. It uses less memory than a QSet<int> if many consecutive numbers are
31 * stored. This is achieved by not storing each number separately, but
32 * "ranges" of numbers.
34 * Example: The set {1, 2, 3, 4, 5} is represented by a single range which
35 * starts at 1 and has the length 5.
37 * 2. When iterating through a KItemSet using KItemSet::iterator or
38 * KItemSet::const_iterator, the numbers are traversed in ascending order.
40 * The complexity of most operations depends on the number of ranges.
47 KItemSet(const KItemSet
& other
);
49 KItemSet
& operator=(const KItemSet
& other
);
52 * Returns the number of items in the set.
53 * Complexity: O(log(number of ranges)).
60 bool operator==(const KItemSet
& other
) const;
61 bool operator!=(const KItemSet
& other
) const;
65 iterator(const KItemRangeList::iterator
& rangeIt
, int offset
) :
72 iterator(const iterator
& other
) :
73 m_rangeIt(other
.m_rangeIt
),
74 m_offset(other
.m_offset
)
78 iterator
& operator=(const iterator
& other
)
80 m_rangeIt
= other
.m_rangeIt
;
81 m_offset
= other
.m_offset
;
85 ~iterator() = default;
89 return m_rangeIt
->index
+ m_offset
;
92 inline bool operator==(const iterator
& other
) const
94 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
97 inline bool operator!=(const iterator
& other
) const
99 return !(*this == other
);
102 inline iterator
& operator++()
106 if (m_offset
== m_rangeIt
->count
) {
114 inline iterator
operator++(int)
121 inline iterator
& operator--()
125 m_offset
= m_rangeIt
->count
- 1;
133 inline iterator
operator--(int)
141 KItemRangeList::iterator m_rangeIt
;
144 friend class const_iterator
;
145 friend class KItemSet
;
151 const_iterator(KItemRangeList::const_iterator rangeIt
, int offset
) :
158 const_iterator(const const_iterator
& other
) :
159 m_rangeIt(other
.m_rangeIt
),
160 m_offset(other
.m_offset
)
164 const_iterator(const iterator
& other
) :
165 m_rangeIt(other
.m_rangeIt
),
166 m_offset(other
.m_offset
)
170 const_iterator
& operator=(const const_iterator
& other
)
172 m_rangeIt
= other
.m_rangeIt
;
173 m_offset
= other
.m_offset
;
177 ~const_iterator() = default;
179 int operator*() const
181 return m_rangeIt
->index
+ m_offset
;
184 inline bool operator==(const const_iterator
& other
) const
186 return m_rangeIt
== other
.m_rangeIt
&& m_offset
== other
.m_offset
;
189 inline bool operator!=(const const_iterator
& other
) const
191 return !(*this == other
);
194 inline const_iterator
& operator++()
198 if (m_offset
== m_rangeIt
->count
) {
206 inline const_iterator
operator++(int)
208 const_iterator r
= *this;
213 inline const_iterator
& operator--()
217 m_offset
= m_rangeIt
->count
- 1;
225 inline const_iterator
operator--(int)
227 const_iterator r
= *this;
233 KItemRangeList::const_iterator m_rangeIt
;
236 friend class KItemSet
;
240 const_iterator
begin() const;
241 const_iterator
constBegin() const;
243 const_iterator
end() const;
244 const_iterator
constEnd() const;
249 bool contains(int i
) const;
250 iterator
insert(int i
);
251 iterator
find(int i
);
252 const_iterator
constFind(int i
) const;
254 iterator
erase(iterator it
);
257 * Returns a new set which contains all items that are contained in this
258 * KItemSet, in \a other, or in both.
260 KItemSet
operator+(const KItemSet
& other
) const;
263 * Returns a new set which contains all items that are contained either in
264 * this KItemSet, or in \a other, but not in both (the symmetric difference
265 * of both KItemSets).
267 KItemSet
operator^(const KItemSet
& other
) const;
269 KItemSet
& operator<<(int i
);
273 * Returns true if the KItemSet is valid, and false otherwise.
274 * A valid KItemSet must store the item ranges in ascending order, and
275 * the ranges must not overlap.
277 bool isValid() const;
280 * This function returns an iterator that points to the KItemRange which
281 * contains i, or m_itemRanges.end() if no such range exists.
283 KItemRangeList::iterator
rangeForItem(int i
);
286 * This function returns an iterator that points to the KItemRange which
287 * contains i, or m_itemRanges.constEnd() if no such range exists.
289 KItemRangeList::const_iterator
constRangeForItem(int i
) const;
291 KItemRangeList m_itemRanges
;
293 friend class KItemSetTest
;
296 inline KItemSet::KItemSet() :
301 inline KItemSet::KItemSet(const KItemSet
& other
) :
302 m_itemRanges(other
.m_itemRanges
)
306 inline KItemSet::~KItemSet() = default;
308 inline KItemSet
& KItemSet::operator=(const KItemSet
& other
)
310 m_itemRanges
=other
.m_itemRanges
;
314 inline int KItemSet::count() const
317 foreach (const KItemRange
& range
, m_itemRanges
) {
318 result
+= range
.count
;
323 inline bool KItemSet::isEmpty() const
325 return m_itemRanges
.isEmpty();
328 inline void KItemSet::clear()
330 m_itemRanges
.clear();
333 inline bool KItemSet::operator==(const KItemSet
& other
) const
335 return m_itemRanges
== other
.m_itemRanges
;
338 inline bool KItemSet::operator!=(const KItemSet
& other
) const
340 return m_itemRanges
!= other
.m_itemRanges
;
343 inline bool KItemSet::contains(int i
) const
345 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
346 return it
!= m_itemRanges
.end();
349 inline KItemSet::iterator
KItemSet::find(int i
)
351 const KItemRangeList::iterator it
= rangeForItem(i
);
352 if (it
!= m_itemRanges
.end()) {
353 return iterator(it
, i
- it
->index
);
359 inline KItemSet::const_iterator
KItemSet::constFind(int i
) const
361 const KItemRangeList::const_iterator it
= constRangeForItem(i
);
362 if (it
!= m_itemRanges
.constEnd()) {
363 return const_iterator(it
, i
- it
->index
);
369 inline bool KItemSet::remove(int i
)
371 iterator it
= find(i
);
380 inline KItemSet::iterator
KItemSet::begin()
382 return iterator(m_itemRanges
.begin(), 0);
385 inline KItemSet::const_iterator
KItemSet::begin() const
387 return const_iterator(m_itemRanges
.begin(), 0);
390 inline KItemSet::const_iterator
KItemSet::constBegin() const
392 return const_iterator(m_itemRanges
.constBegin(), 0);
395 inline KItemSet::iterator
KItemSet::end()
397 return iterator(m_itemRanges
.end(), 0);
400 inline KItemSet::const_iterator
KItemSet::end() const
402 return const_iterator(m_itemRanges
.end(), 0);
405 inline KItemSet::const_iterator
KItemSet::constEnd() const
407 return const_iterator(m_itemRanges
.constEnd(), 0);
410 inline int KItemSet::first() const
412 return m_itemRanges
.first().index
;
415 inline int KItemSet::last() const
417 const KItemRange
& lastRange
= m_itemRanges
.last();
418 return lastRange
.index
+ lastRange
.count
- 1;
421 inline KItemSet
& KItemSet::operator<<(int i
)