1 | /* |
2 | Copyright (c) 2007 Volker Krause <vkrause@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "imapset.h" |
21 | |
22 | #include <QtCore/QSharedData> |
23 | |
24 | using namespace KIMAP; |
25 | |
26 | class ImapInterval::Private : public QSharedData |
27 | { |
28 | public: |
29 | Private() : |
30 | QSharedData(), |
31 | begin( 0 ), |
32 | end( 0 ) |
33 | {} |
34 | |
35 | Private( const Private &other ) : |
36 | QSharedData( other ) |
37 | { |
38 | begin = other.begin; |
39 | end = other.end; |
40 | } |
41 | |
42 | Id begin; |
43 | Id end; |
44 | }; |
45 | |
46 | class ImapSet::Private : public QSharedData |
47 | { |
48 | public: |
49 | Private() : QSharedData() {} |
50 | Private( const Private &other ) : |
51 | QSharedData( other ) |
52 | { |
53 | intervals = other.intervals; |
54 | } |
55 | |
56 | ImapInterval::List intervals; |
57 | }; |
58 | |
59 | ImapInterval::ImapInterval() : |
60 | d( new Private ) |
61 | { |
62 | } |
63 | |
64 | ImapInterval::ImapInterval(const ImapInterval & other) : |
65 | d( other.d ) |
66 | { |
67 | } |
68 | |
69 | ImapInterval::ImapInterval(Id begin, Id end) : |
70 | d( new Private ) |
71 | { |
72 | d->begin = begin; |
73 | d->end = end; |
74 | } |
75 | |
76 | ImapInterval::~ ImapInterval() |
77 | { |
78 | } |
79 | |
80 | ImapInterval& ImapInterval::operator =(const ImapInterval & other) |
81 | { |
82 | if ( this != &other ) { |
83 | d = other.d; |
84 | } |
85 | return *this; |
86 | } |
87 | |
88 | bool ImapInterval::operator ==(const ImapInterval & other) const |
89 | { |
90 | return ( d->begin == other.d->begin && d->end == other.d->end ); |
91 | } |
92 | |
93 | ImapInterval::Id ImapInterval::size() const |
94 | { |
95 | if ( !d->begin && !d->end ) { |
96 | return 0; |
97 | } |
98 | if ( d->begin && !d->end ) { |
99 | return Q_INT64_C( 0x7FFFFFFFFFFFFFFF ) - d->begin + 1; |
100 | } |
101 | return d->end - d->begin + 1; |
102 | } |
103 | |
104 | bool ImapInterval::hasDefinedBegin() const |
105 | { |
106 | return d->begin != 0; |
107 | } |
108 | |
109 | ImapInterval::Id ImapInterval::begin() const |
110 | { |
111 | return d->begin; |
112 | } |
113 | |
114 | bool ImapInterval::hasDefinedEnd() const |
115 | { |
116 | return d->end != 0; |
117 | } |
118 | |
119 | ImapInterval::Id ImapInterval::end() const |
120 | { |
121 | if ( hasDefinedEnd() ) { |
122 | return d->end; |
123 | } |
124 | return 0xFFFFFFFF; // should be INT_MAX, but where is that defined again? |
125 | } |
126 | |
127 | void ImapInterval::setBegin(Id value) |
128 | { |
129 | Q_ASSERT( value >= 0 ); |
130 | Q_ASSERT( value <= d->end || !hasDefinedEnd() ); |
131 | d->begin = value; |
132 | } |
133 | |
134 | void ImapInterval::setEnd(Id value) |
135 | { |
136 | Q_ASSERT( value >= 0 ); |
137 | Q_ASSERT( value >= d->begin || !hasDefinedBegin() ); |
138 | d->end = value; |
139 | } |
140 | |
141 | QByteArray ImapInterval::toImapSequence() const |
142 | { |
143 | if ( size() == 0 ) { |
144 | return QByteArray(); |
145 | } |
146 | if ( size() == 1 ) { |
147 | return QByteArray::number( d->begin ); |
148 | } |
149 | QByteArray rv; |
150 | rv += QByteArray::number( d->begin ) + ':'; |
151 | if ( hasDefinedEnd() ) { |
152 | rv += QByteArray::number( d->end ); |
153 | } else { |
154 | rv += '*'; |
155 | } |
156 | return rv; |
157 | } |
158 | |
159 | ImapInterval ImapInterval::fromImapSequence( const QByteArray &sequence ) |
160 | { |
161 | QList<QByteArray> values = sequence.split( ':' ); |
162 | if ( values.isEmpty() || values.size() > 2 ) { |
163 | return ImapInterval(); |
164 | } |
165 | |
166 | bool ok = false; |
167 | Id begin = values[0].toLongLong( &ok ); |
168 | |
169 | if ( !ok ) { |
170 | return ImapInterval(); |
171 | } |
172 | |
173 | Id end; |
174 | |
175 | if ( values.size() == 1 ) { |
176 | end = begin; |
177 | } else if ( values[1] == QByteArray( "*" ) ) { |
178 | end = 0; |
179 | } else { |
180 | ok = false; |
181 | end = values[1].toLongLong( &ok ); |
182 | if ( !ok ) { |
183 | return ImapInterval(); |
184 | } |
185 | } |
186 | |
187 | return ImapInterval( begin, end ); |
188 | } |
189 | |
190 | ImapSet::ImapSet() : |
191 | d( new Private ) |
192 | { |
193 | } |
194 | |
195 | ImapSet::ImapSet( Id begin, Id end ) : |
196 | d( new Private ) |
197 | { |
198 | add( ImapInterval( begin, end ) ); |
199 | } |
200 | |
201 | ImapSet::ImapSet( Id value ) : |
202 | d( new Private ) |
203 | { |
204 | add( QList<Id>() << value ); |
205 | } |
206 | |
207 | ImapSet::ImapSet(const ImapSet & other) : |
208 | d( other.d ) |
209 | { |
210 | } |
211 | |
212 | ImapSet::~ImapSet() |
213 | { |
214 | } |
215 | |
216 | ImapSet & ImapSet::operator =(const ImapSet & other) |
217 | { |
218 | if ( this != &other ) { |
219 | d = other.d; |
220 | } |
221 | return *this; |
222 | } |
223 | |
224 | bool ImapSet::operator ==(const ImapSet &other) const |
225 | { |
226 | if ( d->intervals.size()!=other.d->intervals.size() ) { |
227 | return false; |
228 | } |
229 | |
230 | foreach ( const ImapInterval &interval, d->intervals ) { |
231 | if ( !other.d->intervals.contains( interval ) ) { |
232 | return false; |
233 | } |
234 | } |
235 | |
236 | return true; |
237 | } |
238 | |
239 | void ImapSet::add( Id value ) |
240 | { |
241 | add( QList<Id>() << value ); |
242 | } |
243 | |
244 | void ImapSet::add(const QList<Id> & values) |
245 | { |
246 | QList<Id> vals = values; |
247 | qSort( vals ); |
248 | for ( int i = 0; i < vals.count(); ++i ) { |
249 | const int begin = vals[i]; |
250 | Q_ASSERT( begin >= 0 ); |
251 | if ( i == vals.count() - 1 ) { |
252 | d->intervals << ImapInterval( begin, begin ); |
253 | break; |
254 | } |
255 | do { |
256 | ++i; |
257 | Q_ASSERT( vals[i] >= 0 ); |
258 | if ( vals[i] != ( vals[i - 1] + 1 ) ) { |
259 | --i; |
260 | break; |
261 | } |
262 | } while ( i < vals.count() - 1 ); |
263 | d->intervals << ImapInterval( begin, vals[i] ); |
264 | } |
265 | } |
266 | |
267 | void ImapSet::add(const ImapInterval & interval) |
268 | { |
269 | d->intervals << interval; |
270 | } |
271 | |
272 | QByteArray ImapSet::toImapSequenceSet() const |
273 | { |
274 | QList<QByteArray> rv; |
275 | foreach ( const ImapInterval &interval, d->intervals ) { |
276 | rv << interval.toImapSequence(); |
277 | } |
278 | |
279 | QByteArray result; |
280 | |
281 | if ( !rv.isEmpty() ) { |
282 | result = rv.first(); |
283 | QList<QByteArray>::ConstIterator it = rv.constBegin(); |
284 | ++it; |
285 | for ( ; it != rv.constEnd(); ++it ) { |
286 | result += ',' + ( *it ); |
287 | } |
288 | } |
289 | |
290 | return result; |
291 | } |
292 | |
293 | ImapSet ImapSet::fromImapSequenceSet( const QByteArray &sequence ) |
294 | { |
295 | ImapSet result; |
296 | |
297 | QList<QByteArray> intervals = sequence.split( ',' ); |
298 | |
299 | foreach ( const QByteArray &interval, intervals ) { |
300 | if ( !interval.isEmpty() ) { |
301 | result.add( ImapInterval::fromImapSequence( interval ) ); |
302 | } |
303 | } |
304 | |
305 | return result; |
306 | } |
307 | |
308 | ImapInterval::List ImapSet::intervals() const |
309 | { |
310 | return d->intervals; |
311 | } |
312 | |
313 | bool ImapSet::isEmpty() const |
314 | { |
315 | return d->intervals.isEmpty(); |
316 | } |
317 | |
318 | QDebug& operator<<( QDebug &d, const ImapInterval &interval ) |
319 | { |
320 | d << interval.toImapSequence(); |
321 | return d; |
322 | } |
323 | |
324 | QDebug& operator<<( QDebug &d, const ImapSet &set ) |
325 | { |
326 | d << set.toImapSequenceSet(); |
327 | return d; |
328 | } |
329 | |