knode
knarticlecollection.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stdlib.h>
00016
00017 #include <klocale.h>
00018 #include <kmessagebox.h>
00019 #include <kdebug.h>
00020
00021 #include "knglobals.h"
00022 #include "knarticlecollection.h"
00023 #include "knarticle.h"
00024
00025 #include <QByteArray>
00026
00027 static const int sizeIncr=50;
00028
00029 KNArticleVector::KNArticleVector(KNArticleVector *master, SortingType sorting)
00030 : m_aster(master), l_en(0), s_ize(0), l_ist(0), s_ortType(sorting)
00031 {
00032 }
00033
00034
00035 KNArticleVector::~KNArticleVector()
00036 {
00037 clear();
00038 }
00039
00040
00041 bool KNArticleVector::resize(int s)
00042 {
00043 KNArticle **bak=l_ist;
00044 int nSize;
00045
00046 if(s==0)
00047 nSize=s_ize+sizeIncr;
00048 else
00049 nSize=((s/sizeIncr)+1)*sizeIncr;
00050
00051 l_ist=(KNArticle**) realloc(l_ist, sizeof(KNArticle*)*nSize);
00052
00053 if(!l_ist) {
00054 KMessageBox::error(knGlobals.topWidget, i18n("Memory allocation failed.\nYou should close this application now\nto avoid data loss."));
00055 l_ist=bak;
00056 return false;
00057 }
00058 else {
00059 s_ize=nSize;
00060
00061 return true;
00062 }
00063
00064 }
00065
00066
00067 bool KNArticleVector::append(KNArticle *a, bool autoSort)
00068 {
00069 if( (l_en+1 > s_ize) && !resize())
00070 return false;
00071
00072 l_ist[l_en++]=a;
00073
00074 if(autoSort) sort();
00075 return true;
00076 }
00077
00078
00079 void KNArticleVector::remove(int pos, bool autoDel, bool autoCompact)
00080 {
00081
00082 if(pos < 0 || pos > l_en-1)
00083 return;
00084
00085 if(autoDel)
00086 delete l_ist[pos];
00087
00088 l_ist[pos]=0;
00089
00090 if(autoCompact)
00091 compact();
00092 }
00093
00094
00095 void KNArticleVector::clear()
00096 {
00097 if(l_ist){
00098 if(m_aster==0)
00099 for(int i=0; i<l_en; i++) delete l_ist[i];
00100 free(l_ist);
00101 }
00102
00103 l_ist=0; l_en=0; s_ize=0;
00104 }
00105
00106
00107 void KNArticleVector::compact()
00108 {
00109 int newLen, nullStart=0, nullCnt=0, ptrStart=0, ptrCnt=0;
00110
00111 for(int idx=0; idx<l_en; idx++) {
00112 if(l_ist[idx]==0) {
00113 ptrStart=-1;
00114 ptrCnt=-1;
00115 nullStart=idx;
00116 nullCnt=1;
00117 for(int idx2=idx+1; idx2<l_en; idx2++) {
00118 if(l_ist[idx2]==0) nullCnt++;
00119 else {
00120 ptrStart=idx2;
00121 ptrCnt=1;
00122 break;
00123 }
00124 }
00125 if(ptrStart!=-1) {
00126 for(int idx2=ptrStart+1; idx2<l_en; idx2++) {
00127 if(l_ist[idx2]!=0) ptrCnt++;
00128 else break;
00129 }
00130 memmove(&(l_ist[nullStart]), &(l_ist[ptrStart]), ptrCnt*sizeof(KNArticle*));
00131 for(int idx2=nullStart+ptrCnt; idx2<nullStart+ptrCnt+nullCnt; idx2++)
00132 l_ist[idx2]=0;
00133 idx=nullStart+ptrCnt-1;
00134 }
00135 else break;
00136 }
00137 }
00138 newLen=0;
00139 while(l_ist[newLen]!=0) newLen++;
00140 l_en=newLen;
00141 }
00142
00143
00144 void KNArticleVector::syncWithMaster()
00145 {
00146 if(!m_aster) return;
00147
00148 if(resize(m_aster->l_en)) {
00149 memcpy(l_ist, m_aster->l_ist, (m_aster->l_en) * sizeof(KNArticle*));
00150 l_en=m_aster->l_en;
00151 sort();
00152 }
00153 }
00154
00155
00156 void KNArticleVector::sort()
00157 {
00158 int (*cmp)(const void*,const void*) = 0;
00159
00160 switch(s_ortType) {
00161 case STid:
00162 cmp=compareById;
00163 break;
00164 case STmsgId:
00165 cmp=compareByMsgId;
00166 break;
00167 default:
00168 cmp=0;
00169 break;
00170 }
00171
00172 if(cmp) {
00173
00174 qsort(l_ist, l_en, sizeof(KNArticle*), cmp);
00175 }
00176 }
00177
00178
00179 int KNArticleVector::compareById(const void *p1, const void *p2)
00180 {
00181 KNArticle *a1, *a2;
00182 int rc=0, id1, id2;
00183
00184 a1=*((KNArticle**)(p1));
00185 a2=*((KNArticle**)(p2));
00186
00187 id1=a1->id(),
00188 id2=a2->id();
00189
00190 if( id1 < id2 ) rc=-1;
00191 else if( id1 > id2 ) rc=1;
00192
00193 return rc;
00194 }
00195
00196
00197 int KNArticleVector::compareByMsgId(const void *p1, const void *p2)
00198 {
00199 KNArticle *a1, *a2;
00200 QByteArray mid1, mid2;
00201
00202 a1=*(KNArticle**)(p1);
00203 a2=*(KNArticle**)(p2);
00204
00205 mid1=a1->messageID(true)->as7BitString(false);
00206 mid2=a2->messageID(true)->as7BitString(false);
00207
00208 if(mid1.isNull()) mid1="";
00209 if(mid2.isNull()) mid2="";
00210
00211 return strcmp( mid1.data(), mid2.data() );
00212 }
00213
00214
00215 KNArticle* KNArticleVector::bsearch(int id)
00216 {
00217 int idx=indexForId(id);
00218
00219 return ( idx>-1 ? l_ist[idx] : 0 );
00220 }
00221
00222
00223 KNArticle* KNArticleVector::bsearch( const QByteArray &id )
00224 {
00225 int idx=indexForMsgId(id);
00226
00227 return ( idx>-1 ? l_ist[idx] : 0 );
00228 }
00229
00230
00231 int KNArticleVector::indexForId(int id)
00232 {
00233 if(s_ortType!=STid) return -1;
00234
00235 int start=0, end=l_en, mid=0, currentId=0;
00236 bool found=false;
00237 KNArticle *current=0;
00238
00239 while(start!=end && !found) {
00240 mid=(start+end)/2;
00241 current=l_ist[mid];
00242 currentId=current->id();
00243
00244 if(currentId==id)
00245 found=true;
00246 else if(currentId < id)
00247 start=mid+1;
00248 else
00249 end=mid;
00250 }
00251
00252 if(found)
00253 return mid;
00254 else {
00255 kDebug(5003) << "id" << id << "not found";
00256 return -1;
00257 }
00258 }
00259
00260
00261 int KNArticleVector::indexForMsgId( const QByteArray &id )
00262 {
00263 if(s_ortType!=STmsgId) return -1;
00264
00265 int start=0, end=l_en, mid=0;
00266 QByteArray currentMid;
00267 bool found=false;
00268 KNArticle *current=0;
00269 int cnt=0;
00270
00271 while(start!=end && !found) {
00272 mid=(start+end)/2;
00273 current=l_ist[mid];
00274 currentMid=current->messageID(true)->as7BitString(false);
00275
00276 if(currentMid==id)
00277 found=true;
00278 else if( currentMid < id )
00279 start=mid+1;
00280 else
00281 end=mid;
00282
00283 cnt++;
00284 }
00285
00286 if(found) {
00287
00288
00289
00290 return mid;
00291 }
00292 else {
00293
00294
00295
00296 return -1;
00297 }
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307 KNArticleCollection::KNArticleCollection(KNCollection *p)
00308 : KNCollection(p), l_astID(0), l_ockedArticles(0), n_otUnloadable(false)
00309 {
00310 a_rticles.setSortMode(KNArticleVector::STid);
00311 m_idIndex.setSortMode(KNArticleVector::STmsgId);
00312 m_idIndex.setMaster(&a_rticles);
00313 }
00314
00315
00316
00317 KNArticleCollection::~KNArticleCollection()
00318 {
00319 clear();
00320 }
00321
00322
00323
00324 bool KNArticleCollection::resize(int s)
00325 {
00326 return a_rticles.resize(s);
00327 }
00328
00329
00330
00331 bool KNArticleCollection::append(KNArticle *a, bool autoSync)
00332 {
00333 if(a_rticles.append(a, false)) {
00334 if(a->id()==-1)
00335 a->setId(++l_astID);
00336 if(autoSync)
00337 syncSearchIndex();
00338 return true;
00339 }
00340 return false;
00341
00342 }
00343
00344
00345
00346 void KNArticleCollection::clear()
00347 {
00348 a_rticles.clear();
00349 m_idIndex.clear();
00350 l_astID=0;
00351 }
00352
00353
00354
00355 void KNArticleCollection::compact()
00356 {
00357 a_rticles.compact();
00358 m_idIndex.clear();
00359 }
00360
00361
00362 KNArticle* KNArticleCollection::byId(int id)
00363 {
00364 return a_rticles.bsearch(id);
00365 }
00366
00367
00368 KNArticle* KNArticleCollection::byMessageId( const QByteArray &mid )
00369 {
00370 if(m_idIndex.isEmpty()) {
00371 m_idIndex.syncWithMaster();
00372 kDebug(5003) <<"KNArticleCollection::byMessageId() : created index";
00373 }
00374 return m_idIndex.bsearch(mid);
00375 }
00376
00377
00378 void KNArticleCollection::setLastID()
00379 {
00380 if(a_rticles.length()>0)
00381 l_astID=a_rticles.at(a_rticles.length()-1)->id();
00382 else
00383 l_astID=0;
00384 }
00385
00386
00387 void KNArticleCollection::syncSearchIndex()
00388 {
00389 m_idIndex.syncWithMaster();
00390
00391
00392
00393
00394 }
00395
00396
00397 void KNArticleCollection::clearSearchIndex()
00398 {
00399 m_idIndex.clear();
00400 }