/* knarticlecollection.cpp KNode, the KDE newsreader Copyright (c) 1999-2001 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US */ #include #include #include #include #include "knglobals.h" #include "knarticlecollection.h" #include "knarticle.h" static const int sizeIncr=50; KNArticleVector::KNArticleVector(KNArticleVector *master, SortingType sorting) : m_aster(master), l_en(0), s_ize(0), l_ist(0), s_ortType(sorting) { } KNArticleVector::~KNArticleVector() { clear(); } bool KNArticleVector::resize(int s) { KNArticle **bak=l_ist; int nSize; if(s==0) nSize=s_ize+sizeIncr; else nSize=((s/sizeIncr)+1)*sizeIncr; l_ist=(KNArticle**) realloc(l_ist, sizeof(KNArticle*)*nSize); if(!l_ist) { KMessageBox::error(knGlobals.topWidget, i18n("Memory allocation failed.\nYou should close this application now\nto avoid data loss.")); l_ist=bak; return false; } else { s_ize=nSize; //kdDebug(5003) << "size : " << siz << "\n" << endl; return true; } } bool KNArticleVector::append(KNArticle *a, bool autoSort) { if( (l_en+1 > s_ize) && !resize()) // array too small => try to realloc return false; // allocation failed !! l_ist[l_en++]=a; if(autoSort) sort(); return true; } void KNArticleVector::remove(int pos, bool autoDel, bool autoCompact) { if(pos < 0 || pos > l_en-1) return; if(autoDel) delete l_ist[pos]; l_ist[pos]=0; if(autoCompact) compact(); } void KNArticleVector::clear() { if(l_ist){ if(m_aster==0) for(int i=0; il_en)) { memcpy(l_ist, m_aster->l_ist, (m_aster->l_en) * sizeof(KNArticle*)); l_en=m_aster->l_en; sort(); } } void KNArticleVector::sort() { int (*cmp)(const void*,const void*) = 0; switch(s_ortType) { case STid: cmp=compareById; break; case STmsgId: cmp=compareByMsgId; break; default: cmp=0; break; } if(cmp) { //compact(); // remove null-pointers qsort(l_ist, l_en, sizeof(KNArticle*), cmp); } } int KNArticleVector::compareById(const void *p1, const void *p2) { KNArticle *a1, *a2; int rc=0, id1, id2; a1=*((KNArticle**)(p1)); a2=*((KNArticle**)(p2)); id1=a1->id(), id2=a2->id(); if( id1 < id2 ) rc=-1; else if( id1 > id2 ) rc=1; return rc; } int KNArticleVector::compareByMsgId(const void *p1, const void *p2) { KNArticle *a1, *a2; TQCString mid1, mid2; a1=*(KNArticle**)(p1); a2=*(KNArticle**)(p2); mid1=a1->messageID(true)->as7BitString(false); mid2=a2->messageID(true)->as7BitString(false); if(mid1.isNull()) mid1=""; if(mid2.isNull()) mid2=""; return strcmp( mid1.data(), mid2.data() ); } KNArticle* KNArticleVector::bsearch(int id) { int idx=indexForId(id); return ( idx>-1 ? l_ist[idx] : 0 ); } KNArticle* KNArticleVector::bsearch(const TQCString &id) { int idx=indexForMsgId(id); return ( idx>-1 ? l_ist[idx] : 0 ); } int KNArticleVector::indexForId(int id) { if(s_ortType!=STid) return -1; int start=0, end=l_en, mid=0, currentId=0; bool found=false; KNArticle *current=0; while(start!=end && !found) { mid=(start+end)/2; current=l_ist[mid]; currentId=current->id(); if(currentId==id) found=true; else if(currentId < id) start=mid+1; else end=mid; } if(found) return mid; else { #ifndef NDEBUG tqDebug("knode: KNArticleVector::indexForId() : id=%d not found", id); #endif return -1; } } int KNArticleVector::indexForMsgId(const TQCString &id) { if(s_ortType!=STmsgId) return -1; int start=0, end=l_en, mid=0; TQCString currentMid=0; bool found=false; KNArticle *current=0; int cnt=0; while(start!=end && !found) { mid=(start+end)/2; current=l_ist[mid]; currentMid=current->messageID(true)->as7BitString(false); if(currentMid==id) found=true; else if( strcmp(currentMid.data(), id.data()) < 0 ) start=mid+1; else end=mid; cnt++; } if(found) { /*#ifndef NDEBUG tqDebug("KNArticleVector::indexForMsgID() : msgID=%s found after %d compares", id.data(), cnt); #endif*/ return mid; } else { /*#ifndef NDEBUG tqDebug("knode: KNArticleVector::indexForMsgID() : msgID=%s not found", id.data()); #endif*/ return -1; } } // ------------------------------------------------------------------------------------------- KNArticleCollection::KNArticleCollection(KNCollection *p) : KNCollection(p), l_astID(0), l_ockedArticles(0), n_otUnloadable(false) { a_rticles.setSortMode(KNArticleVector::STid); m_idIndex.setSortMode(KNArticleVector::STmsgId); m_idIndex.setMaster(&a_rticles); } KNArticleCollection::~KNArticleCollection() { clear(); } bool KNArticleCollection::resize(int s) { return a_rticles.resize(s); } bool KNArticleCollection::append(KNArticle *a, bool autoSync) { if(a_rticles.append(a, false)) { if(a->id()==-1) a->setId(++l_astID); if(autoSync) syncSearchIndex(); return true; } return false; } void KNArticleCollection::clear() { a_rticles.clear(); m_idIndex.clear(); l_astID=0; } void KNArticleCollection::compact() { a_rticles.compact(); m_idIndex.clear(); } KNArticle* KNArticleCollection::byId(int id) { return a_rticles.bsearch(id); } KNArticle* KNArticleCollection::byMessageId(const TQCString &mid) { if(m_idIndex.isEmpty()) { m_idIndex.syncWithMaster(); kdDebug(5003) << "KNArticleCollection::byMessageId() : created index" << endl; } return m_idIndex.bsearch(mid); } void KNArticleCollection::setLastID() { if(a_rticles.length()>0) l_astID=a_rticles.at(a_rticles.length()-1)->id(); else l_astID=0; } void KNArticleCollection::syncSearchIndex() { m_idIndex.syncWithMaster(); /*for(int i=0; iid() << " , " << m_idIndex.at(i)->messageID()->as7BitString(false) << endl; } */ } void KNArticleCollection::clearSearchIndex() { m_idIndex.clear(); }