]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kitemset.cpp
Output of licensedigger + manual cleanup afterwards.
[dolphin.git] / src / kitemviews / kitemset.cpp
1 /*
2 * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "kitemset.h"
8
9
10 KItemSet::iterator KItemSet::insert(int i)
11 {
12 if (m_itemRanges.empty()) {
13 m_itemRanges.push_back(KItemRange(i, 1));
14 return iterator(m_itemRanges.begin(), 0);
15 }
16
17 KItemRangeList::iterator rangeBegin = m_itemRanges.begin();
18 if (i < rangeBegin->index) {
19 // The inserted index is smaller than all existing items.
20 if (i == rangeBegin->index - 1) {
21 // Move the beginning of the first range one item to the front.
22 --rangeBegin->index;
23 ++rangeBegin->count;
24 } else {
25 // Insert a new range at the beginning.
26 rangeBegin = m_itemRanges.insert(rangeBegin, KItemRange(i, 1));
27 }
28
29 return iterator(rangeBegin, 0);
30 }
31
32 KItemRangeList::iterator rangeEnd = m_itemRanges.end();
33 KItemRangeList::iterator lastRange = rangeEnd - 1;
34 if (i >= lastRange->index) {
35 // i either belongs to the last range, or it is larger than all existing items.
36 const int lastItemPlus1 = lastRange->index + lastRange->count;
37 if (i == lastItemPlus1) {
38 // Move the end of the last range one item to the back.
39 ++lastRange->count;
40 } else if (i > lastItemPlus1) {
41 // Append a new range.
42 lastRange = m_itemRanges.insert(rangeEnd, KItemRange(i, 1));
43 }
44
45 return iterator(lastRange, i - lastRange->index);
46 }
47
48 // We know that i is between the smallest existing item and the first item
49 // of the last range. Find the lowest range whose 'index' is smaller than i.
50 KItemRangeList::iterator low = rangeBegin;
51 KItemRangeList::iterator high = lastRange;
52
53 while (low + 1 != high) {
54 const int span = high - low;
55 Q_ASSERT(span >= 2);
56
57 KItemRangeList::iterator mid = low + span / 2;
58 if (mid->index > i) {
59 high = mid;
60 } else {
61 low = mid;
62 }
63 }
64
65 Q_ASSERT(low->index <= i && high->index > i);
66
67 if (i == low->index + low->count) {
68 // i is just one item behind the range low.
69 if (i == high->index - 1) {
70 // i closes the gap between low and high. Merge the two ranges.
71 const int newRangeCount = low->count + 1 + high->count;
72 KItemRangeList::iterator behindNewRange = m_itemRanges.erase(high);
73 KItemRangeList::iterator newRange = behindNewRange - 1;
74 newRange->count = newRangeCount;
75 return iterator(newRange, i - newRange->index);
76 } else {
77 // Extend low by one item.
78 ++low->count;
79 return iterator(low, low->count - 1);
80 }
81 } else if (i > low->index + low->count) {
82 if (i == high->index - 1) {
83 // Extend high by one item to the front.
84 --high->index;
85 ++high->count;
86 return iterator(high, 0);
87 } else {
88 // Insert a new range between low and high.
89 KItemRangeList::iterator newRange = m_itemRanges.insert(high, KItemRange(i, 1));
90 return iterator(newRange, 0);
91 }
92 } else {
93 // The range low already contains i.
94 return iterator(low, i - low->index);
95 }
96 }
97
98 KItemSet::iterator KItemSet::erase(iterator it)
99 {
100 KItemRangeList::iterator rangeIt = it.m_rangeIt;
101
102 if (it.m_offset == 0) {
103 // Removed index is at the beginning of a range.
104 if (rangeIt->count > 1) {
105 ++rangeIt->index;
106 --rangeIt->count;
107 } else {
108 // The range only contains the removed index.
109 rangeIt = m_itemRanges.erase(rangeIt);
110 }
111 return iterator(rangeIt, 0);
112 } else if (it.m_offset == rangeIt->count - 1) {
113 // Removed index is at the end of a range.
114 --rangeIt->count;
115 ++rangeIt;
116 return iterator(rangeIt, 0);
117 } else {
118 // The removed index is in the middle of a range.
119 const int newRangeIndex = *it + 1;
120 const int newRangeCount = rangeIt->count - it.m_offset - 1;
121 const KItemRange newRange(newRangeIndex, newRangeCount);
122
123 rangeIt->count = it.m_offset;
124 ++rangeIt;
125 rangeIt = m_itemRanges.insert(rangeIt, newRange);
126
127 return iterator(rangeIt, 0);
128 }
129 }
130
131 KItemSet KItemSet::operator+(const KItemSet& other) const
132 {
133 KItemSet sum;
134
135 KItemRangeList::const_iterator it1 = m_itemRanges.constBegin();
136 KItemRangeList::const_iterator it2 = other.m_itemRanges.constBegin();
137
138 const KItemRangeList::const_iterator end1 = m_itemRanges.constEnd();
139 const KItemRangeList::const_iterator end2 = other.m_itemRanges.constEnd();
140
141 while (it1 != end1 || it2 != end2) {
142 if (it1 == end1) {
143 // We are past the end of 'this' already. Append all remaining
144 // item ranges from 'other'.
145 while (it2 != end2) {
146 sum.m_itemRanges.append(*it2);
147 ++it2;
148 }
149 } else if (it2 == end2) {
150 // We are past the end of 'other' already. Append all remaining
151 // item ranges from 'this'.
152 while (it1 != end1) {
153 sum.m_itemRanges.append(*it1);
154 ++it1;
155 }
156 } else {
157 // Find the beginning of the next range.
158 int index = qMin(it1->index, it2->index);
159 int count = 0;
160
161 do {
162 if (it1 != end1 && it1->index <= index + count) {
163 // The next range from 'this' overlaps with the current range in the sum.
164 count = qMax(count, it1->index + it1->count - index);
165 ++it1;
166 }
167
168 if (it2 != end2 && it2->index <= index + count) {
169 // The next range from 'other' overlaps with the current range in the sum.
170 count = qMax(count, it2->index + it2->count - index);
171 ++it2;
172 }
173 } while ((it1 != end1 && it1->index <= index + count)
174 || (it2 != end2 && it2->index <= index + count));
175
176 sum.m_itemRanges.append(KItemRange(index, count));
177 }
178 }
179
180 return sum;
181 }
182
183 KItemSet KItemSet::operator^(const KItemSet& other) const
184 {
185 // We are looking for all ints which are either in *this or in other,
186 // but not in both.
187 KItemSet result;
188
189 // When we go through all integers from INT_MIN to INT_MAX and start
190 // in the state "do not add to result", every beginning/end of a range
191 // of *this and other toggles the "add/do not add to result" state.
192 // Therefore, we just have to put ints where any range starts/ends to
193 // a sorted array, and then we can calculate the result quite easily.
194 QVector<int> rangeBoundaries;
195 rangeBoundaries.resize(2 * (m_itemRanges.count() + other.m_itemRanges.count()));
196 const QVector<int>::iterator begin = rangeBoundaries.begin();
197 const QVector<int>::iterator end = rangeBoundaries.end();
198 QVector<int>::iterator it = begin;
199
200 foreach (const KItemRange& range, m_itemRanges) {
201 *it++ = range.index;
202 *it++ = range.index + range.count;
203 }
204
205 const QVector<int>::iterator middle = it;
206
207 foreach (const KItemRange& range, other.m_itemRanges) {
208 *it++ = range.index;
209 *it++ = range.index + range.count;
210 }
211 Q_ASSERT(it == end);
212
213 std::inplace_merge(begin, middle, end);
214
215 it = begin;
216 while (it != end) {
217 const int rangeBegin = *it;
218 ++it;
219
220 if (*it == rangeBegin) {
221 // It seems that ranges from both *this and other start at
222 // rangeBegin. Do not start a new range, but read the next int.
223 //
224 // Example: Consider the symmetric difference of the sets
225 // {1, 2, 3, 4} and {1, 2}. The sorted list of range boundaries is
226 // 1 1 3 5. Discarding the duplicate 1 yields the result
227 // rangeBegin = 3, rangeEnd = 5, which corresponds to the set {3, 4}.
228 ++it;
229 } else {
230 // The end of the current range is the next *single* int that we
231 // find. If an int appears twice in rangeBoundaries, the range does
232 // not end.
233 //
234 // Example: Consider the symmetric difference of the sets
235 // {1, 2, 3, 4, 8, 9, 10} and {5, 6, 7}. The sorted list of range
236 // boundaries is 1 5 5 8 8 11, and discarding all duplicates yields
237 // the result rangeBegin = 1, rangeEnd = 11, which corresponds to
238 // the set {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}.
239 bool foundEndOfRange = false;
240 int rangeEnd;
241 do {
242 rangeEnd = *it;
243 ++it;
244
245 if (it == end || *it != rangeEnd) {
246 foundEndOfRange = true;
247 } else {
248 ++it;
249 }
250 } while (!foundEndOfRange);
251
252 result.m_itemRanges.append(KItemRange(rangeBegin, rangeEnd - rangeBegin));
253 }
254 }
255
256 return result;
257 }
258
259 bool KItemSet::isValid() const
260 {
261 const KItemRangeList::const_iterator begin = m_itemRanges.constBegin();
262 const KItemRangeList::const_iterator end = m_itemRanges.constEnd();
263
264 for (KItemRangeList::const_iterator it = begin; it != end; ++it) {
265 if (it->count <= 0) {
266 return false;
267 }
268
269 if (it != begin) {
270 const KItemRangeList::const_iterator previous = it - 1;
271 if (previous->index + previous->count >= it->index) {
272 return false;
273 }
274 }
275 }
276
277 return true;
278 }
279
280 KItemRangeList::iterator KItemSet::rangeForItem(int i)
281 {
282 const KItemRangeList::iterator end = m_itemRanges.end();
283 KItemRangeList::iterator low = m_itemRanges.begin();
284 KItemRangeList::iterator high = end;
285
286 if (low == end || low->index > i) {
287 return end;
288 }
289
290 while (low != high && low + 1 != high) {
291 KItemRangeList::iterator mid = low + (high - low) / 2;
292 if (mid->index > i) {
293 high = mid;
294 } else {
295 low = mid;
296 }
297 }
298
299 Q_ASSERT(low->index <= i);
300 if (low->index + low->count > i) {
301 return low;
302 }
303
304 return end;
305 }
306
307 KItemRangeList::const_iterator KItemSet::constRangeForItem(int i) const
308 {
309 const KItemRangeList::const_iterator end = m_itemRanges.constEnd();
310 KItemRangeList::const_iterator low = m_itemRanges.constBegin();
311 KItemRangeList::const_iterator high = end;
312
313 if (low == end || low->index > i) {
314 return end;
315 }
316
317 while (low != high && low + 1 != high) {
318 KItemRangeList::const_iterator mid = low + (high - low) / 2;
319 if (mid->index > i) {
320 high = mid;
321 } else {
322 low = mid;
323 }
324 }
325
326 Q_ASSERT(low->index <= i);
327 if (low->index + low->count > i) {
328 return low;
329 }
330
331 return end;
332 }