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