qvaluelist.h

Go to the documentation of this file.
00001 /********************************************************************************
00002 *                                                                               *
00003 *                   Q t   V a l u e   L i s t   T h u n k                       *
00004 *                                                                               *
00005 *********************************************************************************
00006 * Copyright (C) 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 QVALUELIST_H
00023 #define QVALUELIST_H
00024 
00025 #if _MSC_VER==1200
00026 #pragma warning(disable: 4786)
00027 #endif
00028 
00029 #include <list>
00030 #undef Unsorted
00031 #include "fxdefs.h"
00032 #include "FXException.h"
00033 #include "FXPolicies.h"
00034 #include "FXStream.h"
00035 
00036 namespace FX {
00037 
00038 typedef FXuint uint;
00039 
00057 template<class type> class QValueList : public std::list<type>
00058 {
00059 public:
00060     QValueList() : std::list<type>() { }
00061     QValueList(const std::list<type> &l) : std::list<type>(l) { }
00062     FXADDMOVEBASECLASS(QValueList, std::list<type>)
00063     void remove(const type &d) { std::list<type>::remove(d); }
00064     uint removeAllOf(const type &d)
00065     {
00066         uint count=0;
00067         for(typename std::list<type>::iterator it=std::list<type>::begin(); it!=std::list<type>::end(); ++it)
00068         {
00069             if(*it==d) count++;
00070         }
00071         for(uint n=0; n<count; n++)
00072             std::list<type>::remove(d);
00073         return count;
00074     }
00075     bool isEmpty() const { return std::list<type>::empty(); }
00076     typename std::list<type>::iterator append(const type &d) { FXEXCEPTION_STL1 { std::list<type>::push_back(d); } FXEXCEPTION_STL2; return --std::list<type>::end(); }
00077     typename std::list<type>::iterator append(const QValueList &l)
00078     {
00079         FXEXCEPTION_STL1 {
00080             for(typename std::list<type>::const_iterator it=l.begin(); it!=l.end(); ++it)
00081             {
00082                 std::list<type>::push_back(*it);
00083             }
00084         } FXEXCEPTION_STL2;
00085         return --std::list<type>::end();
00086     }
00087     typename std::list<type>::iterator prepend(const type &d) { FXEXCEPTION_STL1 { std::list<type>::push_front(d); } FXEXCEPTION_STL2; return std::list<type>::begin(); }
00088     typename std::list<type>::iterator remove(typename std::list<type>::iterator it) { typename std::list<type>::iterator itafter=it; ++itafter; std::list<type>::erase(it); return itafter; }
00089     typename std::list<type>::iterator at(typename std::list<type>::size_type i) { typename std::list<type>::iterator it; for(it=std::list<type>::begin(); i; --i, ++it); return it; }
00090     typename std::list<type>::const_iterator at(typename std::list<type>::size_type i) const { typename std::list<type>::const_iterator it; for(it=std::list<type>::begin(); i; --i, ++it); return it; }
00091     type &operator[](typename std::list<type>::size_type i) { return *at(i); }
00092     const type &operator[](typename std::list<type>::size_type i) const { return *at(i); }
00093     typename std::list<type>::iterator find(const type &d)
00094     {
00095         typename std::list<type>::iterator it;
00096         for(it=std::list<type>::begin(); it!=std::list<type>::end(); ++it)
00097             if(*it==d) return it;
00098         return it;
00099     }
00100     typename std::list<type>::const_iterator find(const type &d) const
00101     {
00102         typename std::list<type>::const_iterator it;
00103         for(it=std::list<type>::begin(); it!=std::list<type>::end(); ++it)
00104             if(*it==d) return it;
00105         return it;
00106     }
00107     typename std::list<type>::iterator find(typename std::list<type>::iterator it, const type &d)
00108     {
00109         for(; it!=std::list<type>::end(); ++it)
00110             if(*it==d) return it;
00111         return it;
00112     }
00113     typename std::list<type>::const_iterator find(typename std::list<type>::const_iterator it, const type &d) const
00114     {
00115         for(; it!=std::list<type>::end(); ++it)
00116             if(*it==d) return it;
00117         return it;
00118     }
00119     int findIndex(const type &d) const
00120     {
00121         int idx=0;
00122         for(typename std::list<type>::const_iterator it=std::list<type>::begin(); it!=std::list<type>::end(); ++it, ++idx)
00123             if(*it==d) return idx;
00124         return -1;
00125     }
00126     typename std::list<type>::size_type contains(const type &d) const
00127     {
00128         typename std::list<type>::size_type count=0;
00129         for(typename std::list<type>::const_iterator it=std::list<type>::begin(); it!=std::list<type>::end(); ++it)
00130             if(*it==d) count++;
00131         return count;
00132     }
00133     typename std::list<type>::size_type count() const { return std::list<type>::size(); }
00134     QValueList<type> &operator+=(const type &d) { std::list<type>::push_back(d); return *this; }
00135 
00136 };
00137 
00138 // Unfortunately GCC doesn't like templated typedefs (at last one area MSVC wins!)
00139 //template<class type> typedef typename std::list<type>::iterator QValueListIterator;
00140 //template<class type> typedef typename std::list<type>::const_iterator QValueListConstIterator;
00141 
00148 template<class type> class QValueListIterator : public std::list<type>::iterator
00149 {
00150 public:
00151     QValueListIterator() : std::list<type>::iterator() { }
00152     QValueListIterator(const QValueListIterator &o) : std::list<type>::iterator(o) { }
00153 };
00160 template<class type> class QValueListConstIterator : public std::list<type>::const_iterator
00161 {
00162 public:
00163     QValueListConstIterator() : std::list<type>::const_iterator() { }
00164     QValueListConstIterator(const QValueListConstIterator &o) : std::list<type>::const_iterator(o) { }
00165 };
00166 
00168 template<class type> FXStream &operator<<(FXStream &s, const QValueList<type> &i)
00169 {
00170     FXuint mysize=(FXuint) i.count();
00171     s << mysize;
00172     for(typename QValueList<type>::const_iterator it=i.begin(); it!=i.end(); ++it)
00173     {
00174         s << *it;
00175     }
00176     return s;
00177 }
00179 template<class type> FXStream &operator>>(FXStream &s, QValueList<type> &i)
00180 {
00181     FXuint mysize;
00182     s >> mysize;
00183     i.clear();
00184     for(FXuint n=0; n<mysize; n++)
00185     {
00186         type item;
00187         s >> item;
00188         i.append(item);
00189     }
00190     return s;
00191 }
00192 
00194 enum QVLQSortType
00195 {
00196     QVLQSortDefault=0,      
00197     QVLQSortInsertion=1,    
00198     QVLQSortMerge=2,        
00199     QVLQSortQuick=4,        
00200 
00201     QVLQSortStable=256      
00202 };
00280 template<class type,
00281     template<class> class movePolicy=Pol::itMove,
00282     template<class> class swapPolicy=Pol::itSwap,
00283     template<class> class comparePolicy=Pol::itCompare>
00284 class QValueListQSort : public movePolicy<type>, public swapPolicy<type>, public comparePolicy<type>
00285 {
00286     static const int insertionCutOff=12, mergeCutOff=12; //40000;
00287 public:
00288     typedef QValueList<type> list;
00289     typedef typename list::iterator iterator;
00290 protected:
00291     typedef std::pair<int, iterator> intit;
00292     mutable list &mylist;
00293     int sorttype;
00294 public:
00296     QValueListQSort(QValueList<type> &list, int _sorttype=QVLQSortDefault)
00297         : mylist(list), sorttype(_sorttype) { }
00299     void run(int _sorttype=QVLQSortDefault)
00300     {
00301         if(mylist.empty()) return;
00302         if(QVLQSortDefault!=sorttype) sorttype=_sorttype;
00303         if(!sorttype) sorttype=QVLQSortInsertion|QVLQSortMerge|QVLQSortQuick;
00304         int s=(int) mylist.size();
00305         if(s>mergeCutOff && (sorttype & QVLQSortQuick) && !(sorttype & QVLQSortStable))
00306         {
00307             intit l=std::make_pair(0, mylist.begin());
00308             intit u=std::make_pair(s, mylist.end());
00309             qsort(l, u);
00310         }
00311         //else if(s>insertionCutOff && (sorttype & QVLQSortMerge))
00312         //{
00313         //  msort();
00314         //}
00315         else
00316         {
00317             iterator l=mylist.begin(), u=mylist.end();
00318             isort(l, u);
00319         }
00320     }
00321 private:
00322     void isort(iterator &lb, iterator &ub)
00323     {   // Niall's bastard iterator based insertion sort
00324         for(iterator it=lb;;)
00325         {
00326             iterator prev=it;
00327             if(++it==ub) break;
00328             if(comparePolicy<type>::compare(mylist, it, prev))
00329             {
00330                 bool found=false;
00331                 iterator find=lb;
00332                 for(; find!=ub; ++find)
00333                 {
00334                     if(find!=it && comparePolicy<type>::compare(mylist, it, find))
00335                     {
00336                         bool atStart=(find==lb);
00337                         move(mylist, find, it);
00338                         if(atStart) lb=it;
00339                         found=true;
00340                         break;
00341                     }
00342                 }
00343                 if(!found) movePolicy<type>::move(mylist, find, it);
00344             }
00345         }
00346     }
00347     inline void merge(int len, intit &_lb, intit &_m, intit &_ub)
00348     {
00349         bool updlb=true, updm=true, updub=true;
00350         iterator lb=_lb.second, m=_m.second, ub=_ub.second;
00351         while(true)
00352         {
00353             // To be completed
00354         }
00355     }
00356     void msort(intit &_lb, intit &_ub)
00357     {
00358         int len=(_ub.first-_lb.first);
00359         if(len<=2) return;
00360         int mididx=len>>1;
00361         iterator it=_lb.second;
00362         int idx;
00363         for(idx=_lb.first; idx<mididx; ++it, ++idx);
00364         intit m=std::make_pair(idx, it);
00365         msort(_lb, m);
00366         msort(m, _ub);
00367         merge(len, _lb, m, _ub);
00368     }
00369     inline intit partition(intit &_lb, intit &_ub)
00370     {
00371         bool updlb=true;
00372         int lbidx=_lb.first, ubidx=_ub.first;
00373         iterator lb(_lb.second), ub(_ub.second);
00374         while(true)
00375         {
00376             while(lbidx<ubidx && comparePolicy<type>::compare(mylist, _lb.second, (--ubidx, --ub)));
00377             while(lbidx<ubidx && comparePolicy<type>::compare(mylist, (updlb=false, ++lbidx, ++lb), _lb.second));
00378             if(lbidx>=ubidx) break;
00379             swapPolicy<type>::swap(mylist, lb, ub);
00380             if(updlb) _lb.second=lb;
00381         }
00382         if(_lb.second!=ub)
00383         {
00384             swapPolicy<type>::swap(mylist, _lb.second, ub);
00385         }
00386         return std::make_pair(ubidx, ub);
00387     }
00388     void qsort(intit &_lb, intit &_ub)
00389     {
00390         bool updlb=true, updub=true;
00391         intit lb(_lb), ub(_ub);
00392         while(lb.first<ub.first)
00393         {
00394             if(ub.first-lb.first<=insertionCutOff)
00395             {
00396                 isort(lb.second, ub.second);
00397                 if(updlb) _lb.second=lb.second;
00398                 if(updub) _ub.second=ub.second;
00399                 return;
00400             }
00401             intit i=partition(lb, ub);
00402             if(updlb) _lb.second=lb.second;
00403             if(updub) _ub.second=ub.second;
00404             int r1=i.first-lb.first, r2=ub.first-i.first-1;
00405             if(r1<=r2)
00406             {
00407                 if(r1>0)
00408                 {
00409                     qsort(lb, i);
00410                     if(updlb) _lb.second=lb.second;
00411                 }
00412                 lb.first=i.first+1; lb.second=++i.second; updlb=false;
00413             }
00414             else
00415             {
00416                 ++i.first; ++i.second;
00417                 if(r2>0)
00418                 {
00419                     qsort(i, ub);
00420                     if(updub) _ub.second=ub.second;
00421                 }
00422                 ub.first=i.first-1; ub.second=--i.second; updub=false;
00423             }
00424         }
00425     }
00426 };
00427 
00428 } // namespace
00429 
00430 #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