00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00130
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
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
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
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
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 {
00293 std::list<type *, allocator>::splice(it.int_getIterator(), static_cast<std::list<type *, allocator> &>(list), nit2.int_getIterator());
00294
00295
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 }
00330
00331 #endif