File indexing completed on 2024-04-28 05:45:10
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KITEMSET_H 0008 #define KITEMSET_H 0009 0010 #include "dolphin_export.h" 0011 #include "kitemviews/kitemrange.h" 0012 0013 /** 0014 * @brief Stores a set of integer numbers in a space-efficient way. 0015 * 0016 * This class is similar to QSet<int>, but it has the following advantages: 0017 * 0018 * 1. It uses less memory than a QSet<int> if many consecutive numbers are 0019 * stored. This is achieved by not storing each number separately, but 0020 * "ranges" of numbers. 0021 * 0022 * Example: The set {1, 2, 3, 4, 5} is represented by a single range which 0023 * starts at 1 and has the length 5. 0024 * 0025 * 2. When iterating through a KItemSet using KItemSet::iterator or 0026 * KItemSet::const_iterator, the numbers are traversed in ascending order. 0027 * 0028 * The complexity of most operations depends on the number of ranges. 0029 */ 0030 0031 class DOLPHIN_EXPORT KItemSet 0032 { 0033 public: 0034 KItemSet(); 0035 KItemSet(const KItemSet &other); 0036 ~KItemSet(); 0037 KItemSet &operator=(const KItemSet &other); 0038 0039 /** 0040 * Returns the number of items in the set. 0041 * Complexity: O(log(number of ranges)). 0042 */ 0043 int count() const; 0044 0045 bool isEmpty() const; 0046 void clear(); 0047 0048 bool operator==(const KItemSet &other) const; 0049 bool operator!=(const KItemSet &other) const; 0050 0051 class iterator 0052 { 0053 iterator(const KItemRangeList::iterator &rangeIt, int offset = 0) 0054 : m_rangeIt(rangeIt) 0055 , m_offset(offset) 0056 { 0057 } 0058 0059 public: 0060 iterator(const iterator &other) 0061 : m_rangeIt(other.m_rangeIt) 0062 , m_offset(other.m_offset) 0063 { 0064 } 0065 0066 iterator &operator=(const iterator &other) 0067 { 0068 m_rangeIt = other.m_rangeIt; 0069 m_offset = other.m_offset; 0070 return *this; 0071 } 0072 0073 ~iterator() = default; 0074 0075 int operator*() const 0076 { 0077 return m_rangeIt->index + m_offset; 0078 } 0079 0080 inline bool operator==(const iterator &other) const 0081 { 0082 return m_rangeIt == other.m_rangeIt && m_offset == other.m_offset; 0083 } 0084 0085 inline bool operator!=(const iterator &other) const 0086 { 0087 return !(*this == other); 0088 } 0089 0090 inline iterator &operator++() 0091 { 0092 ++m_offset; 0093 0094 if (m_offset == m_rangeIt->count) { 0095 ++m_rangeIt; 0096 m_offset = 0; 0097 } 0098 0099 return *this; 0100 } 0101 0102 inline iterator operator++(int) 0103 { 0104 iterator r = *this; 0105 ++(*this); 0106 return r; 0107 } 0108 0109 inline iterator &operator--() 0110 { 0111 if (m_offset == 0) { 0112 --m_rangeIt; 0113 m_offset = m_rangeIt->count - 1; 0114 } else { 0115 --m_offset; 0116 } 0117 0118 return *this; 0119 } 0120 0121 inline iterator operator--(int) 0122 { 0123 iterator r = *this; 0124 --(*this); 0125 return r; 0126 } 0127 0128 private: 0129 KItemRangeList::iterator m_rangeIt; 0130 int m_offset; 0131 0132 friend class const_iterator; 0133 friend class KItemSet; 0134 }; 0135 0136 class const_iterator 0137 { 0138 const_iterator(KItemRangeList::const_iterator rangeIt, int offset = 0) 0139 : m_rangeIt(rangeIt) 0140 , m_offset(offset) 0141 { 0142 } 0143 0144 public: 0145 const_iterator(const const_iterator &other) 0146 : m_rangeIt(other.m_rangeIt) 0147 , m_offset(other.m_offset) 0148 { 0149 } 0150 0151 explicit const_iterator(const iterator &other) 0152 : m_rangeIt(other.m_rangeIt) 0153 , m_offset(other.m_offset) 0154 { 0155 } 0156 0157 const_iterator &operator=(const const_iterator &other) 0158 { 0159 m_rangeIt = other.m_rangeIt; 0160 m_offset = other.m_offset; 0161 return *this; 0162 } 0163 0164 ~const_iterator() = default; 0165 0166 int operator*() const 0167 { 0168 return m_rangeIt->index + m_offset; 0169 } 0170 0171 inline bool operator==(const const_iterator &other) const 0172 { 0173 return m_rangeIt == other.m_rangeIt && m_offset == other.m_offset; 0174 } 0175 0176 inline bool operator!=(const const_iterator &other) const 0177 { 0178 return !(*this == other); 0179 } 0180 0181 inline const_iterator &operator++() 0182 { 0183 ++m_offset; 0184 0185 if (m_offset == m_rangeIt->count) { 0186 ++m_rangeIt; 0187 m_offset = 0; 0188 } 0189 0190 return *this; 0191 } 0192 0193 inline const_iterator operator++(int) 0194 { 0195 const_iterator r = *this; 0196 ++(*this); 0197 return r; 0198 } 0199 0200 inline const_iterator &operator--() 0201 { 0202 if (m_offset == 0) { 0203 --m_rangeIt; 0204 m_offset = m_rangeIt->count - 1; 0205 } else { 0206 --m_offset; 0207 } 0208 0209 return *this; 0210 } 0211 0212 inline const_iterator operator--(int) 0213 { 0214 const_iterator r = *this; 0215 --(*this); 0216 return r; 0217 } 0218 0219 private: 0220 KItemRangeList::const_iterator m_rangeIt; 0221 int m_offset; 0222 0223 friend class KItemSet; 0224 }; 0225 0226 class const_reverse_iterator 0227 { 0228 public: 0229 const_reverse_iterator(KItemSet::const_iterator rangeIt) 0230 : m_current(rangeIt) 0231 { 0232 } 0233 0234 const_reverse_iterator(const KItemSet::const_reverse_iterator &other) 0235 : m_current(other.base()) 0236 { 0237 } 0238 0239 int operator*() const 0240 { 0241 // analog to std::prev 0242 auto t = const_iterator(m_current); 0243 --t; 0244 return *t; 0245 } 0246 0247 inline bool operator==(const const_reverse_iterator &other) const 0248 { 0249 return m_current == other.m_current; 0250 } 0251 0252 bool operator!=(const const_reverse_iterator &other) const 0253 { 0254 return !(*this == other); 0255 } 0256 0257 const_reverse_iterator &operator++() 0258 { 0259 --m_current; 0260 return *this; 0261 } 0262 const_reverse_iterator operator++(int) 0263 { 0264 auto tmp = *this; 0265 ++(*this); 0266 return tmp; 0267 } 0268 0269 const_reverse_iterator &operator--() 0270 { 0271 ++m_current; 0272 return *this; 0273 } 0274 const_reverse_iterator operator--(int) 0275 { 0276 auto tmp = *this; 0277 --(*this); 0278 return tmp; 0279 } 0280 0281 KItemSet::const_iterator base() const 0282 { 0283 return m_current; 0284 } 0285 0286 private: 0287 KItemSet::const_iterator m_current; 0288 }; 0289 0290 iterator begin(); 0291 const_iterator begin() const; 0292 const_iterator constBegin() const; 0293 iterator end(); 0294 const_iterator end() const; 0295 const_iterator constEnd() const; 0296 0297 const_reverse_iterator rend() const; 0298 const_reverse_iterator rbegin() const; 0299 0300 int first() const; 0301 int last() const; 0302 0303 bool contains(int i) const; 0304 iterator insert(int i); 0305 iterator find(int i); 0306 const_iterator constFind(int i) const; 0307 bool remove(int i); 0308 iterator erase(iterator it); 0309 0310 /** 0311 * Returns a new set which contains all items that are contained in this 0312 * KItemSet, in \a other, or in both. 0313 */ 0314 KItemSet operator+(const KItemSet &other) const; 0315 0316 /** 0317 * Returns a new set which contains all items that are contained either in 0318 * this KItemSet, or in \a other, but not in both (the symmetric difference 0319 * of both KItemSets). 0320 */ 0321 KItemSet operator^(const KItemSet &other) const; 0322 0323 KItemSet &operator<<(int i); 0324 0325 private: 0326 /** 0327 * Returns true if the KItemSet is valid, and false otherwise. 0328 * A valid KItemSet must store the item ranges in ascending order, and 0329 * the ranges must not overlap. 0330 */ 0331 bool isValid() const; 0332 0333 /** 0334 * This function returns an iterator that points to the KItemRange which 0335 * contains i, or m_itemRanges.end() if no such range exists. 0336 */ 0337 KItemRangeList::iterator rangeForItem(int i); 0338 0339 /** 0340 * This function returns an iterator that points to the KItemRange which 0341 * contains i, or m_itemRanges.constEnd() if no such range exists. 0342 */ 0343 KItemRangeList::const_iterator constRangeForItem(int i) const; 0344 0345 KItemRangeList m_itemRanges; 0346 0347 friend class KItemSetTest; 0348 }; 0349 0350 inline KItemSet::KItemSet() 0351 : m_itemRanges() 0352 { 0353 } 0354 0355 inline KItemSet::KItemSet(const KItemSet &other) 0356 : m_itemRanges(other.m_itemRanges) 0357 { 0358 } 0359 0360 inline KItemSet::~KItemSet() = default; 0361 0362 inline KItemSet &KItemSet::operator=(const KItemSet &other) 0363 { 0364 m_itemRanges = other.m_itemRanges; 0365 return *this; 0366 } 0367 0368 inline int KItemSet::count() const 0369 { 0370 int result = 0; 0371 for (const KItemRange &range : std::as_const(m_itemRanges)) { 0372 result += range.count; 0373 } 0374 return result; 0375 } 0376 0377 inline bool KItemSet::isEmpty() const 0378 { 0379 return m_itemRanges.isEmpty(); 0380 } 0381 0382 inline void KItemSet::clear() 0383 { 0384 m_itemRanges.clear(); 0385 } 0386 0387 inline bool KItemSet::operator==(const KItemSet &other) const 0388 { 0389 return m_itemRanges == other.m_itemRanges; 0390 } 0391 0392 inline bool KItemSet::operator!=(const KItemSet &other) const 0393 { 0394 return m_itemRanges != other.m_itemRanges; 0395 } 0396 0397 inline bool KItemSet::contains(int i) const 0398 { 0399 const KItemRangeList::const_iterator it = constRangeForItem(i); 0400 return it != m_itemRanges.end(); 0401 } 0402 0403 inline KItemSet::iterator KItemSet::find(int i) 0404 { 0405 const KItemRangeList::iterator it = rangeForItem(i); 0406 if (it != m_itemRanges.end()) { 0407 return iterator(it, i - it->index); 0408 } else { 0409 return end(); 0410 } 0411 } 0412 0413 inline KItemSet::const_iterator KItemSet::constFind(int i) const 0414 { 0415 const KItemRangeList::const_iterator it = constRangeForItem(i); 0416 if (it != m_itemRanges.constEnd()) { 0417 return const_iterator(it, i - it->index); 0418 } else { 0419 return constEnd(); 0420 } 0421 } 0422 0423 inline bool KItemSet::remove(int i) 0424 { 0425 iterator it = find(i); 0426 if (it != end()) { 0427 erase(it); 0428 return true; 0429 } else { 0430 return false; 0431 } 0432 } 0433 0434 inline KItemSet::iterator KItemSet::begin() 0435 { 0436 return iterator(m_itemRanges.begin()); 0437 } 0438 0439 inline KItemSet::const_iterator KItemSet::begin() const 0440 { 0441 return const_iterator(m_itemRanges.begin()); 0442 } 0443 0444 inline KItemSet::const_iterator KItemSet::constBegin() const 0445 { 0446 return const_iterator(m_itemRanges.constBegin()); 0447 } 0448 0449 inline KItemSet::iterator KItemSet::end() 0450 { 0451 return iterator(m_itemRanges.end()); 0452 } 0453 0454 inline KItemSet::const_iterator KItemSet::end() const 0455 { 0456 return const_iterator(m_itemRanges.end()); 0457 } 0458 0459 inline KItemSet::const_iterator KItemSet::constEnd() const 0460 { 0461 return const_iterator(m_itemRanges.constEnd()); 0462 } 0463 0464 inline int KItemSet::first() const 0465 { 0466 return m_itemRanges.first().index; 0467 } 0468 0469 inline int KItemSet::last() const 0470 { 0471 const KItemRange &lastRange = m_itemRanges.last(); 0472 return lastRange.index + lastRange.count - 1; 0473 } 0474 0475 inline KItemSet::const_reverse_iterator KItemSet::rend() const 0476 { 0477 return KItemSet::const_reverse_iterator(constBegin()); 0478 } 0479 0480 inline KItemSet::const_reverse_iterator KItemSet::rbegin() const 0481 { 0482 return KItemSet::const_reverse_iterator(constEnd()); 0483 } 0484 0485 inline KItemSet &KItemSet::operator<<(int i) 0486 { 0487 insert(i); 0488 return *this; 0489 } 0490 0491 #endif