KIMAP

imapset.cpp
1/*
2 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "imapset.h"
8
9#include <QSharedData>
10
11using namespace KIMAP;
12
13class ImapInterval::Private : public QSharedData
14{
15public:
16 Private()
17 : QSharedData()
18 , begin(0)
19 , end(0)
20 {
21 }
22
23 Private(const Private &other)
24 : QSharedData(other)
25 , begin(other.begin)
26 , end(other.end)
27 {
28 }
29
30 Id begin;
31 Id end;
32};
33
34class ImapSet::Private : public QSharedData
35{
36public:
37 Private()
38 : QSharedData()
39 {
40 }
41 Private(const Private &other)
42 : QSharedData(other)
43 , intervals(other.intervals)
44 {
45 }
46
47 ImapInterval::List intervals;
48};
49
51 : d(new Private)
52{
53}
54
56 : d(other.d)
57{
58}
59
61 : d(new Private)
62{
63 d->begin = begin;
64 d->end = end;
65}
66
70
72{
73 if (this != &other) {
74 d = other.d;
75 }
76 return *this;
77}
78
79bool ImapInterval::operator==(const ImapInterval &other) const
80{
81 return (d->begin == other.d->begin && d->end == other.d->end);
82}
83
85{
86 if (!d->begin && !d->end) {
87 return 0;
88 }
89 if (d->begin && !d->end) {
90 return Q_INT64_C(0x7FFFFFFFFFFFFFFF) - d->begin + 1;
91 }
92 return d->end - d->begin + 1;
93}
94
96{
97 return d->begin != 0;
98}
99
101{
102 return d->begin;
103}
104
106{
107 return d->end != 0;
108}
109
111{
112 if (hasDefinedEnd()) {
113 return d->end;
114 }
115 return std::numeric_limits<qint64>::max();
116}
117
119{
120 Q_ASSERT(value >= 0);
121 Q_ASSERT(value <= d->end || !hasDefinedEnd());
122 d->begin = value;
123}
124
126{
127 Q_ASSERT(value >= 0);
128 Q_ASSERT(value >= d->begin || !hasDefinedBegin());
129 d->end = value;
130}
131
133{
134 if (size() == 0) {
135 return QByteArray();
136 }
137 if (size() == 1) {
138 return QByteArray::number(d->begin);
139 }
140 QByteArray rv = QByteArray::number(d->begin) + ':';
141 if (hasDefinedEnd()) {
142 rv += QByteArray::number(d->end);
143 } else {
144 rv += '*';
145 }
146 return rv;
147}
148
150{
151 QList<QByteArray> values = sequence.split(':');
152 if (values.isEmpty() || values.size() > 2) {
153 return ImapInterval();
154 }
155
156 bool ok = false;
157 Id begin = values[0].toLongLong(&ok);
158
159 if (!ok) {
160 return ImapInterval();
161 }
162
163 Id end;
164
165 if (values.size() == 1) {
166 end = begin;
167 } else if (values[1] == QByteArray("*")) {
168 end = 0;
169 } else {
170 ok = false;
171 end = values[1].toLongLong(&ok);
172 if (!ok) {
173 return ImapInterval();
174 }
175 }
176
177 return ImapInterval(begin, end);
178}
179
181 : d(new Private)
182{
183}
184
186 : d(new Private)
187{
188 add(ImapInterval(begin, end));
189}
190
192 : d(new Private)
193{
194 add(QList<Id>() << value);
195}
196
198 : d(other.d)
199{
200}
201
205
207{
208 if (this != &other) {
209 d = other.d;
210 }
211 return *this;
212}
213
214bool ImapSet::operator==(const ImapSet &other) const
215{
216 if (d->intervals.size() != other.d->intervals.size()) {
217 return false;
218 }
219
220 for (const ImapInterval &interval : std::as_const(d->intervals)) {
221 if (!other.d->intervals.contains(interval)) {
222 return false;
223 }
224 }
225
226 return true;
227}
228
229void ImapSet::add(Id value)
230{
231 add(QList<Id>() << value);
232}
233
234void ImapSet::add(const QList<Id> &values)
235{
236 QList<Id> vals = values;
237 std::sort(vals.begin(), vals.end());
238 for (int i = 0; i < vals.count(); ++i) {
239 const Id begin = vals[i];
240 Q_ASSERT(begin >= 0);
241 if (i == vals.count() - 1) {
242 d->intervals << ImapInterval(begin, begin);
243 break;
244 }
245 do {
246 ++i;
247 Q_ASSERT(vals[i] >= 0);
248 if (vals[i] != (vals[i - 1] + 1)) {
249 --i;
250 break;
251 }
252 } while (i < vals.count() - 1);
253 d->intervals << ImapInterval(begin, vals[i]);
254 }
255}
256
257void ImapSet::add(const ImapInterval &interval)
258{
259 d->intervals << interval;
260}
261
263{
265 rv.reserve(d->intervals.count());
266 for (const ImapInterval &interval : std::as_const(d->intervals)) {
267 rv << interval.toImapSequence();
268 }
269
270 QByteArray result;
271
272 if (!rv.isEmpty()) {
273 result = rv.first();
276 ++it;
277 for (; it != end; ++it) {
278 result += ',' + (*it);
279 }
280 }
281
282 return result;
283}
284
286{
287 ImapSet result;
288
289 const QList<QByteArray> intervals = sequence.split(',');
290
291 for (const QByteArray &interval : std::as_const(intervals)) {
292 if (!interval.isEmpty()) {
293 result.add(ImapInterval::fromImapSequence(interval));
294 }
295 }
296
297 return result;
298}
299
301{
302 return d->intervals;
303}
304
306{
307 return d->intervals.isEmpty();
308}
309
311{
312 // There's nothing to optimize if we have fewer than 2 intervals
313 if (d->intervals.size() < 2) {
314 return;
315 }
316
317 // Sort the intervals in ascending order by their beginning value
318 std::sort(d->intervals.begin(), d->intervals.end(), [](const ImapInterval &lhs, const ImapInterval &rhs) {
319 return lhs.begin() < rhs.begin();
320 });
321
322 auto it = d->intervals.begin();
323 while (it != d->intervals.end() && it != std::prev(d->intervals.end())) {
324 auto next = std::next(it);
325 // +1 so that we also merge neighbouring intervals, e.g. 1:2,3:4 -> 1:4
326 if (it->hasDefinedEnd() && it->end() + 1 >= next->begin()) {
327 next->setBegin(it->begin());
328 if (next->hasDefinedEnd() && it->end() > next->end()) {
329 next->setEnd(it->end());
330 }
331 it = d->intervals.erase(it);
332 } else if (!it->hasDefinedEnd()) {
333 // We can eat up all the remaining intervals
334 it = d->intervals.erase(next, d->intervals.end());
335 } else {
336 ++it;
337 }
338 }
339}
340
341QDebug &operator<<(QDebug &d, const ImapInterval &interval)
342{
343 d << interval.toImapSequence();
344 return d;
345}
346
347QDebug &operator<<(QDebug &d, const ImapSet &set)
348{
349 d << set.toImapSequenceSet();
350 return d;
351}
Represents a single interval in an ImapSet.
Definition imapset.h:24
bool hasDefinedBegin() const
Returns true if this interval has a defined begin.
Definition imapset.cpp:95
ImapInterval()
Constructs an interval that covers all positive numbers.
Definition imapset.cpp:50
ImapInterval & operator=(const ImapInterval &other)
Assignment operator.
Definition imapset.cpp:71
static ImapInterval fromImapSequence(const QByteArray &sequence)
Return the interval corresponding to the given IMAP-compatible QByteArray representation.
Definition imapset.cpp:149
~ImapInterval()
Destructor.
Definition imapset.cpp:67
Id end() const
Returns the end of this interval.
Definition imapset.cpp:110
Id begin() const
Returns the begin of this interval.
Definition imapset.cpp:100
void setEnd(Id value)
Sets the end of this interval.
Definition imapset.cpp:125
Id size() const
Returns the size of this interval.
Definition imapset.cpp:84
bool operator==(const ImapInterval &other) const
Comparison operator.
Definition imapset.cpp:79
bool hasDefinedEnd() const
Returns true if this intercal has been defined.
Definition imapset.cpp:105
void setBegin(Id value)
Sets the begin of the interval.
Definition imapset.cpp:118
qint64 Id
Describes the ids stored in the interval.
Definition imapset.h:29
QByteArray toImapSequence() const
Converts this set into an IMAP compatible sequence.
Definition imapset.cpp:132
Represents a set of natural numbers (1->∞) in a as compact as possible form.
Definition imapset.h:127
~ImapSet()
Destructor.
Definition imapset.cpp:202
qint64 Id
Describes the ids stored in the set.
Definition imapset.h:132
bool isEmpty() const
Returns true if this set doesn't contains any values.
Definition imapset.cpp:305
ImapSet()
Constructs an empty set.
Definition imapset.cpp:180
void optimize()
Optimizes the ImapSet by sorting and merging overlapping intervals.
Definition imapset.cpp:310
QByteArray toImapSequenceSet() const
Returns a IMAP-compatible QByteArray representation of this set.
Definition imapset.cpp:262
void add(Id value)
Adds a single positive integer numbers to the set.
Definition imapset.cpp:229
static ImapSet fromImapSequenceSet(const QByteArray &sequence)
Return the set corresponding to the given IMAP-compatible QByteArray representation.
Definition imapset.cpp:285
bool operator==(const ImapSet &other) const
Comparison operator.
Definition imapset.cpp:214
ImapInterval::List intervals() const
Returns the intervals this set consists of.
Definition imapset.cpp:300
ImapSet & operator=(const ImapSet &other)
Assignment operator.
Definition imapset.cpp:206
QByteArray number(double n, char format, int precision)
QList< QByteArray > split(char sep) const const
iterator begin()
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
iterator end()
T & first()
bool isEmpty() const const
void reserve(qsizetype size)
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:06:50 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.