qsortedlist.h

Go to the documentation of this file.
00001 /********************************************************************************
00002 *                                                                               *
00003 *                         An always sorted qptrlist                             *
00004 *                                                                               *
00005 *********************************************************************************
00006 * Copyright (C) 2001,2002,2003 by Niall Douglas.   All Rights Reserved.         *
00007 *       NOTE THAT I DO NOT PERMIT ANY OF MY CODE TO BE PROMOTED TO THE GPL      *
00008 *********************************************************************************
00009 * This code is free software; you can redistribute it and/or modify it under    *
00010 * the terms of the GNU Library General Public License v2.1 as published by the  *
00011 * Free Software Foundation EXCEPT that clause 3 does not apply ie; you may not  *
00012 * "upgrade" this code to the GPL without my prior written permission.           *
00013 * Please consult the file "License_Addendum2.txt" accompanying this file.       *
00014 *                                                                               *
00015 * This code is distributed in the hope that it will be useful,                  *
00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                          *
00018 *********************************************************************************
00019 * $Id:                                                                          *
00020 ********************************************************************************/
00021 
00022 #ifndef QSORTEDLIST_H
00023 #define QSORTEDLIST_H
00024 
00025 #include <qptrlist.h>
00030 namespace FX {
00050 template<class type, class allocator=FX::aligned_allocator<type *, 0> > class QSortedListIterator;
00051 template<class type, class allocator=FX::aligned_allocator<type *, 0> > class QSortedList;
00052 template<class type, class allocator> class QSortedList : private QPtrList<type, allocator>
00053 {
00054     bool findInternal(QSortedListIterator<type, allocator> *itout, int *idx, const type *d) const;
00055     QSortedListIterator<type, allocator> findRefInternal(const type *d) const;
00056 public:
00057     explicit QSortedList(bool wantAutoDel=false) : QPtrList<type>(wantAutoDel) {}
00058     QSortedList(const QSortedList<type, allocator> &o) : QPtrList<type>(o) {}
00059     ~QSortedList()              { clear(); }
00060     QSortedList<type, allocator> &operator=(const QSortedList<type, allocator> &l)
00061             { return (QSortedList<type, allocator>&)QPtrList<type>::operator=(l); }
00062     FXADDMOVEBASECLASS(QSortedList, QPtrList<type>)
00063     bool operator==( const QSortedList<type, allocator> &list ) const
00064     { return QPtrList<type>::operator==( list ); }
00065 
00066     using QPtrList<type>::autoDelete;
00067     using QPtrList<type>::setAutoDelete;
00068     using QPtrList<type>::count;
00069     using QPtrList<type>::isEmpty;
00070     using QPtrList<type>::removeByIter;
00071     using QPtrList<type>::removeFirst;
00072     using QPtrList<type>::removeLast;
00073     using QPtrList<type>::takeByIter;
00074     using QPtrList<type>::takeFirst;
00075     using QPtrList<type>::takeLast;
00076     using QPtrList<type>::clear;
00077     using QPtrList<type>::contains;
00078     using QPtrList<type>::containsRef;
00079     using QPtrList<type>::at;
00080     using QPtrList<type>::getFirst;
00081     using QPtrList<type>::getLast;
00082     using QPtrList<type>::first;
00083     using QPtrList<type>::last;
00088     virtual int compareItems(type *a, type *b) const;
00090     bool remove(const type *d);
00092     bool removeRef(const type *d);
00094     bool take(const type *d);
00096     bool takeRef(const type *d);
00098     int find(const type *d) const { int idx; if(findInternal(0, &idx, d)) return idx; else return -1; }
00100     QSortedListIterator<type, allocator> findIter(const type *d) const;
00102     type *findP(const type *d) const;
00107     int findClosest(const type *d) const { int idx; findInternal(0, &idx, d); return idx; }
00110     QSortedListIterator<type, allocator> findClosestIter(const type *d) const;
00113     type *findClosestP(const type *d) const;
00118     bool insert(const type *d);
00122     void merge(QSortedList<type, allocator> &list, bool exclusive=false);
00123 };
00124 
00125 template<class type, class allocator> inline int QSortedList<type, allocator>::compareItems(type *a, type *b) const
00126 {
00127     if(*a==*b) return 0;
00128     return (*a<*b) ? -1 : 1;
00129     //if(*((QSortedListItem<type> *) s1)==*((QSortedListItem<type> *) s2)) return 0;
00130     //return (*((QSortedListItem<type> *) s1)<*((QSortedListItem<type> *) s2) ? -1 : 1 );
00131 }
00132 template<> inline int QSortedList<void>::compareItems(void *a, void *b) const
00133 {
00134     if(a==b) return 0;
00135     return (a<b) ? -1 : 1;
00136 }
00137 
00147 template<class type, class allocator> class QSortedListIterator : public QPtrListIterator<type, allocator>
00148 {
00149 public:
00150     QSortedListIterator() { }
00151     QSortedListIterator(const QSortedList<type, allocator> &l)
00152         : QPtrListIterator<type, allocator>((const QPtrList<type, allocator> &) l) {}
00154     QSortedListIterator<type, allocator> &makeDead()
00155     {
00156         return static_cast<QSortedListIterator<type, allocator> &>(QPtrListIterator<type, allocator>::makeDead());
00157     }
00158 };
00159 
00160 template<class type, class allocator> inline QSortedListIterator<type, allocator> QSortedList<type, allocator>::findRefInternal(const type *d) const
00161 {
00162     QSortedListIterator<type, allocator> it;
00163     if(!findInternal(&it, 0, d)) return it.makeDead();
00164     QSortedListIterator<type, allocator> it1(it), it2(it);
00165     type *a;
00166     // Step backwards while comparitor is equal
00167     for(--it; (a=it.current()) && !compareItems(const_cast<type *>(d), a); it1=it, --it);
00168     for(it=it1; (a=it.current()); ++it)
00169     {
00170         if(a==d) return it;
00171         if(it==it2) break;
00172     }
00173     // Step forwards while comparitor is equal
00174     for(; (a=it.current()) && !compareItems(const_cast<type *>(d), a); ++it)
00175     {
00176         if(a==d) return it;
00177     }
00178     return it.makeDead();
00179 }
00180 
00181 template<class type, class allocator> inline bool QSortedList<type, allocator>::remove(const type *d)
00182 {
00183     QSortedListIterator<type, allocator> it;
00184     if(!findInternal(&it, 0, d)) return false;
00185     return QPtrList<type>::removeByIter(it);
00186 }
00187 
00188 template<class type, class allocator> inline bool QSortedList<type, allocator>::removeRef(const type *d)
00189 {
00190     QSortedListIterator<type, allocator> it(findRefInternal(d));
00191     if(!it.current()) return false;
00192     return QPtrList<type>::removeByIter(it);
00193 }
00194 
00195 template<class type, class allocator> inline bool QSortedList<type, allocator>::take(const type *d)
00196 {
00197     QSortedListIterator<type, allocator> it;
00198     if(!findInternal(&it, 0, d)) return false;
00199     return QPtrList<type>::takeByIter(it);
00200 }
00201 
00202 template<class type, class allocator> inline bool QSortedList<type, allocator>::takeRef(const type *d)
00203 {
00204     QSortedListIterator<type, allocator> it(findRefInternal(d));
00205     if(!it.current()) return false;
00206     return QPtrList<type>::takeByIter(it);
00207 }
00208 
00209 template<class type, class allocator> inline QSortedListIterator<type, allocator> QSortedList<type, allocator>::findIter(const type *d) const
00210 {
00211     QSortedListIterator<type, allocator> it;
00212     if(!findInternal(&it, 0, d))
00213         it.makeDead();
00214     return it;
00215 }
00216 
00217 template<class type, class allocator> inline type *QSortedList<type, allocator>::findP(const type *d) const
00218 {
00219     QSortedListIterator<type, allocator> it;
00220     if(!findInternal(&it, 0, d)) return 0;
00221     return it.current();
00222 }
00223 
00224 template<class type, class allocator> inline QSortedListIterator<type, allocator> QSortedList<type, allocator>::findClosestIter(const type *d) const
00225 {
00226     QSortedListIterator<type, allocator> it;
00227     findInternal(&it, 0, d);
00228     return it;
00229 }
00230 
00231 template<class type, class allocator> inline type *QSortedList<type, allocator>::findClosestP(const type *d) const
00232 {
00233     QSortedListIterator<type, allocator> it;
00234     findInternal(&it, 0, d);
00235     return it.current();
00236 }
00237 
00238 template<class type, class allocator> inline bool QSortedList<type, allocator>::insert(const type *d)
00239 {
00240     QSortedListIterator<type, allocator> it;
00241     findInternal(&it, 0, d);
00242     return QPtrList<type>::insertAtIter(it, d);
00243 }
00244 
00245 template<class type, class allocator> inline bool QSortedList<type, allocator>::findInternal(QSortedListIterator<type, allocator> *itout, int *idx, const type *d) const
00246 {
00247     int n=0;
00248     QSortedListIterator<type, allocator> it(*this); it.toFirst();
00249     int lbound=0, ubound=count()-1, c;
00250     //if(lbound<0) lbound=0;
00251     while(lbound<=ubound)
00252     {
00253         int result;
00254         const type *testpoint;
00255         c=(lbound+ubound)/2;
00256         if(c-n>0) { testpoint=it+=(c-n); n=c; }
00257         else if(c-n<0) { testpoint=it-=(n-c); n=c; }
00258         else testpoint=it.current();
00259         // Unfortunate that I have to do this, but compareItems() should really be const
00260         QSortedList<type, allocator> *t=const_cast<QSortedList<type, allocator> *>(this);
00261         result=t->compareItems(const_cast<type *>(d), const_cast<type *>(testpoint));
00262         if(result<0)
00263             ubound=c-1;
00264         else if(result>0)
00265             lbound=c+1;
00266         else
00267         {
00268             if(itout) *itout=it;
00269             if(idx) *idx=n;
00270             return true;
00271         }
00272     }
00273     if(itout)
00274     {
00275         if(lbound!=n) it+=(lbound-n);
00276         *itout=it;
00277     }
00278     if(idx) *idx=lbound;
00279     return false;
00280 }
00281 
00282 template<class type, class allocator> inline void QSortedList<type, allocator>::merge(QSortedList<type, allocator> &list, bool exclusive)
00283 {
00284     QSortedListIterator<type, allocator> it;
00285     type *ne;
00286     for(QSortedListIterator<type, allocator> nit(list); (ne=nit.current());)
00287     {
00288         QSortedListIterator<type, allocator> nit2(nit); ++nit;
00289         if(findInternal(&it, 0, ne) && exclusive)
00290             QPtrList<type>::removeByIter(nit2);
00291         else
00292         {   // Might as well splice as it avoids malloc
00293             std::list<type *, allocator>::splice(it.int_getIterator(), static_cast<std::list<type *, allocator> &>(list), nit2.int_getIterator());
00294             //QPtrList<type>::insertAtIter(it, ne);
00295             //list.takeByIter(nit2);
00296         }
00297     }
00298 }
00299 
00301 template<class type, class allocator> FXStream &operator<<(FXStream &s, const QSortedList<type, allocator> &i)
00302 {
00303     FXuint mysize=i.count();
00304     s << mysize;
00305     for(QSortedListIterator<type, allocator> it(i); it.current(); ++it)
00306     {
00307         s << *it.current();
00308     }
00309     return s;
00310 }
00312 template<class type, class allocator> FXStream &operator>>(FXStream &s, QSortedList<type, allocator> &i)
00313 {
00314     QPtrList<type, allocator> &ii=(QPtrList<type, allocator> &) i;
00315     FXuint mysize;
00316     s >> mysize;
00317     i.clear();
00318     for(FXuint n=0; n<mysize; n++)
00319     {
00320         type *item;
00321         FXERRHM(item=new type);
00322         s >> *item;
00323         ii.append(item);
00324     }
00325     return s;
00326 }
00327 
00328 
00329 } // namespace
00330 
00331 #endif

(C) 2002-2009 Niall Douglas. Some parts (C) to assorted authors.
Generated on Fri Nov 20 18:31:26 2009 for TnFOX by doxygen v1.4.7