You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/knode/knarticlecollection.cpp

404 lines
7.4 KiB

/*
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 <stdlib.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kdebug.h>
#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; i<l_en; i++) delete l_ist[i];
free(l_ist);
}
l_ist=0; l_en=0; s_ize=0;
}
void KNArticleVector::compact()
{
int newLen, nullStart=0, nullCnt=0, ptrStart=0, ptrCnt=0;
for(int idx=0; idx<l_en; idx++) {
if(l_ist[idx]==0) {
ptrStart=-1;
ptrCnt=-1;
nullStart=idx;
nullCnt=1;
for(int idx2=idx+1; idx2<l_en; idx2++) {
if(l_ist[idx2]==0) nullCnt++;
else {
ptrStart=idx2;
ptrCnt=1;
break;
}
}
if(ptrStart!=-1) {
for(int idx2=ptrStart+1; idx2<l_en; idx2++) {
if(l_ist[idx2]!=0) ptrCnt++;
else break;
}
memmove(&(l_ist[nullStart]), &(l_ist[ptrStart]), ptrCnt*sizeof(KNArticle*));
for(int idx2=nullStart+ptrCnt; idx2<nullStart+ptrCnt+nullCnt; idx2++)
l_ist[idx2]=0;
idx=nullStart+ptrCnt-1;
}
else break;
}
}
newLen=0;
while(l_ist[newLen]!=0) newLen++;
l_en=newLen;
}
void KNArticleVector::syncWithMaster()
{
if(!m_aster) return;
if(resize(m_aster->l_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; i<m_idIndex.length(); i++) {
kdDebug(5003) << m_idIndex.at(i)->id() << " , " << m_idIndex.at(i)->messageID()->as7BitString(false) << endl;
} */
}
void KNArticleCollection::clearSearchIndex()
{
m_idIndex.clear();
}