00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "imapset.h"
00021
00022 #include <QtCore/QSharedData>
00023
00024 using namespace KIMAP;
00025
00026 class ImapInterval::Private : public QSharedData
00027 {
00028 public:
00029 Private() :
00030 QSharedData(),
00031 begin( 0 ),
00032 end( 0 )
00033 {}
00034
00035 Private( const Private &other ) :
00036 QSharedData( other )
00037 {
00038 begin = other.begin;
00039 end = other.end;
00040 }
00041
00042 Id begin;
00043 Id end;
00044 };
00045
00046 class ImapSet::Private : public QSharedData
00047 {
00048 public:
00049 Private() : QSharedData() {}
00050 Private( const Private &other ) :
00051 QSharedData( other )
00052 {
00053 intervals = other.intervals;
00054 }
00055
00056 ImapInterval::List intervals;
00057 };
00058
00059
00060 ImapInterval::ImapInterval() :
00061 d( new Private )
00062 {
00063 }
00064
00065 ImapInterval::ImapInterval(const ImapInterval & other) :
00066 d( other.d )
00067 {
00068 }
00069
00070 ImapInterval::ImapInterval(Id begin, Id end) :
00071 d( new Private )
00072 {
00073 d->begin = begin;
00074 d->end = end;
00075 }
00076
00077 ImapInterval::~ ImapInterval()
00078 {
00079 }
00080
00081 ImapInterval& ImapInterval::operator =(const ImapInterval & other)
00082 {
00083 if ( this != & other )
00084 d = other.d;
00085 return *this;
00086 }
00087
00088 bool ImapInterval::operator ==(const ImapInterval & other) const
00089 {
00090 return ( d->begin == other.d->begin && d->end == other.d->end );
00091 }
00092
00093 ImapInterval::Id ImapInterval::size() const
00094 {
00095 if ( !d->begin && !d->end )
00096 return 0;
00097 if ( d->begin && !d->end )
00098 return Q_INT64_C( 0x7FFFFFFFFFFFFFFF ) - d->begin + 1;
00099 return d->end - d->begin + 1;
00100 }
00101
00102 bool ImapInterval::hasDefinedBegin() const
00103 {
00104 return d->begin != 0;
00105 }
00106
00107 ImapInterval::Id ImapInterval::begin() const
00108 {
00109 return d->begin;
00110 }
00111
00112 bool ImapInterval::hasDefinedEnd() const
00113 {
00114 return d->end != 0;
00115 }
00116
00117 ImapInterval::Id ImapInterval::end() const
00118 {
00119 if ( hasDefinedEnd() )
00120 return d->end;
00121 return 0xFFFFFFFF;
00122 }
00123
00124 void ImapInterval::setBegin(Id value)
00125 {
00126 Q_ASSERT( value >= 0 );
00127 Q_ASSERT( value <= d->end || !hasDefinedEnd() );
00128 d->begin = value;
00129 }
00130
00131 void ImapInterval::setEnd(Id value)
00132 {
00133 Q_ASSERT( value >= 0 );
00134 Q_ASSERT( value >= d->begin || !hasDefinedBegin() );
00135 d->end = value;
00136 }
00137
00138 QByteArray ImapInterval::toImapSequence() const
00139 {
00140 if ( size() == 0 )
00141 return QByteArray();
00142 if ( size() == 1 )
00143 return QByteArray::number( d->begin );
00144 QByteArray rv;
00145 rv += QByteArray::number( d->begin ) + ':';
00146 if ( hasDefinedEnd() )
00147 rv += QByteArray::number( d->end );
00148 else
00149 rv += '*';
00150 return rv;
00151 }
00152
00153 ImapInterval ImapInterval::fromImapSequence( const QByteArray &sequence )
00154 {
00155 QList<QByteArray> values = sequence.split( ':' );
00156 if ( values.isEmpty() || values.size() > 2 ) {
00157 return ImapInterval();
00158 }
00159
00160 bool ok = false;
00161 Id begin = values[0].toLongLong(&ok);
00162
00163 if ( !ok ) {
00164 return ImapInterval();
00165 }
00166
00167 Id end;
00168
00169 if ( values.size() == 1 ) {
00170 end = begin;
00171 } else if ( values[1] == QByteArray( "*" ) ) {
00172 end = 0;
00173 } else {
00174 ok = false;
00175 end = values[1].toLongLong(&ok);
00176 if ( !ok ) {
00177 return ImapInterval();
00178 }
00179 }
00180
00181 return ImapInterval( begin, end );
00182 }
00183
00184 ImapSet::ImapSet() :
00185 d( new Private )
00186 {
00187 }
00188
00189 ImapSet::ImapSet( Id begin, Id end ) :
00190 d( new Private )
00191 {
00192 add( ImapInterval( begin, end ) );
00193 }
00194
00195 ImapSet::ImapSet( Id value ) :
00196 d( new Private )
00197 {
00198 add( QList<Id>() << value );
00199 }
00200
00201 ImapSet::ImapSet(const ImapSet & other) :
00202 d( other.d )
00203 {
00204 }
00205
00206 ImapSet::~ImapSet()
00207 {
00208 }
00209
00210 ImapSet & ImapSet::operator =(const ImapSet & other)
00211 {
00212 if ( this != &other )
00213 d = other.d;
00214 return *this;
00215 }
00216
00217 bool ImapSet::operator ==(const ImapSet &other) const
00218 {
00219 if ( d->intervals.size()!=other.d->intervals.size() ) {
00220 return false;
00221 }
00222
00223 foreach ( const ImapInterval &interval, d->intervals ) {
00224 if ( !other.d->intervals.contains( interval ) ) {
00225 return false;
00226 }
00227 }
00228
00229 return true;
00230 }
00231
00232 void ImapSet::add( Id value )
00233 {
00234 add( QList<Id>() << value );
00235 }
00236
00237 void ImapSet::add(const QList<Id> & values)
00238 {
00239 QList<Id> vals = values;
00240 qSort( vals );
00241 for( int i = 0; i < vals.count(); ++i ) {
00242 const int begin = vals[i];
00243 Q_ASSERT( begin >= 0 );
00244 if ( i == vals.count() - 1 ) {
00245 d->intervals << ImapInterval( begin, begin );
00246 break;
00247 }
00248 do {
00249 ++i;
00250 Q_ASSERT( vals[i] >= 0 );
00251 if ( vals[i] != (vals[i - 1] + 1) ) {
00252 --i;
00253 break;
00254 }
00255 } while ( i < vals.count() - 1 );
00256 d->intervals << ImapInterval( begin, vals[i] );
00257 }
00258 }
00259
00260 void ImapSet::add(const ImapInterval & interval)
00261 {
00262 d->intervals << interval;
00263 }
00264
00265 QByteArray ImapSet::toImapSequenceSet() const
00266 {
00267 QList<QByteArray> rv;
00268 foreach ( const ImapInterval &interval, d->intervals ) {
00269 rv << interval.toImapSequence();
00270 }
00271
00272 QByteArray result;
00273
00274 if ( !rv.isEmpty() ) {
00275 result = rv.first();
00276 QList<QByteArray>::ConstIterator it = rv.constBegin();
00277 ++it;
00278 for ( ; it != rv.constEnd(); ++it ) {
00279 result += ',' + (*it);
00280 }
00281 }
00282
00283 return result;
00284 }
00285
00286 ImapSet ImapSet::fromImapSequenceSet( const QByteArray &sequence )
00287 {
00288 ImapSet result;
00289
00290 QList<QByteArray> intervals = sequence.split( ',' );
00291
00292 foreach( const QByteArray &interval, intervals ) {
00293 if ( !interval.isEmpty() ) {
00294 result.add( ImapInterval::fromImapSequence( interval ) );
00295 }
00296 }
00297
00298 return result;
00299 }
00300
00301 ImapInterval::List ImapSet::intervals() const
00302 {
00303 return d->intervals;
00304 }
00305
00306 bool ImapSet::isEmpty() const
00307 {
00308 return d->intervals.isEmpty();
00309 }
00310
00311 QDebug& operator<<( QDebug &d, const ImapInterval &interval )
00312 {
00313 d << interval.toImapSequence();
00314 return d;
00315 }
00316
00317 QDebug& operator<<( QDebug &d, const ImapSet &set )
00318 {
00319 d << set.toImapSequenceSet();
00320 return d;
00321 }
00322