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