Gizmo3D

gzTemplates.h

Go to the documentation of this file.
00001 //*****************************************************************************
00002 // File         : gzTemplates.h
00003 // Module       : gzBase
00004 // Description  : Class definition of iterator utilities
00005 // Author       : Anders Modén      
00006 // Product      : GizmoBase 2.1.1
00007 //      
00008 // Copyright © 2003- Saab Training Systems AB, Sweden    
00009 //          
00010 // NOTE:    GizmoBase is a platform abstraction utility layer for C++. It contains 
00011 //          design patterns and C++ solutions for the advanced programmer.
00012 //
00013 //
00014 // Revision History...                          
00015 //                                  
00016 // Who  Date    Description                     
00017 //                                  
00018 // AMO  980915  Created file    
00019 //
00020 //******************************************************************************
00021 
00022 #ifndef __GZ_TEMPLATES_H__
00023 #define __GZ_TEMPLATES_H__
00024 
00025 
00034 #include "gzBasicTypes.h"
00035 #include "gzMemory.h"
00036 #include "gzAssembler.h"
00037 
00038 #include <float.h>
00039 
00040 // Forward prototyp
00041 GZ_BASE_EXPORT gzVoid throwFatalTemplateError(char *string);
00042 
00043 
00044 template <class T> class gzListIterator;
00045 template <class T> class gzListConstIterator;
00046 template <class T> class gzRefList;
00047 
00048 //******************************************************************************
00049 // Template : gzList
00050 //                                  
00051 // Purpose  : Linked list with index insort and reference management
00052 //                                  
00053 // Notes    : -
00054 //                                  
00055 // Revision History...                          
00056 //                                  
00057 // Who  Date    Description                     
00058 //                                  
00059 // AMO  980601  Created 
00060 //                                  
00061 //******************************************************************************
00072 template <class T> class gzList 
00073 {
00074     friend class gzListIterator<T>; 
00075     friend class gzListConstIterator<T>; 
00076     friend class gzRefList<T>;
00077 
00078     public:
00079 
00081         gzList(gzBool reuseLinks=FALSE);
00082 
00084 
00090         gzList(const gzList<T> &copy)  ;
00091 
00093         virtual ~gzList()  ;
00094 
00096         gzVoid insert(T *item)  ;                   // Adds at end of list
00097 
00099         gzVoid insertAt(gzULong index,T *item)  ;   // Adds at index
00100 
00102         gzVoid pre_insert(T *item) ;                    // Adds at beginning of list
00103 
00105 
00109         T   *insert(T *item, gzDouble sortval)  ;
00110 
00112 
00114         gzBool post_insert(T *item, gzDouble sortval)  ;
00115 
00117 
00119         gzBool pre_insert(T *item, gzDouble sortval)  ;
00120 
00122         T   *operator[](gzULong i)  ;
00123 
00125         gzList &operator=(const gzList &copy )  ;
00126 
00127         gzList &operator+=(const gzList &copy )  ;
00128 
00130         virtual gzVoid clear()  ;
00131 
00133         virtual gzVoid clearAndDestroy()  ;
00134 
00136         gzULong entries() const  ;
00137 
00139         gzBool contains(const T *item) const  ;
00140 
00141         T   *findSortItem(gzDouble sortval,const T *prevItem=NULL);
00142 
00144         T   *removeFirst()  ;
00145         
00147         T   *removeLast()  ;
00148 
00150         T   *remove( T * item )  ;
00151         
00153         T   *removeAt( gzULong index )  ;
00154 
00156         T   *last() const;
00157 
00159         T   *first() const;
00160 
00162         virtual gzVoid onInsert(T *item ) const {};
00163 
00165         virtual gzVoid onRemove(T *item ) const {};
00166 
00168 
00173         virtual T* cloneEntry(T *item ) const ;
00174 
00176         gzVoid  cleanLinks()  ;
00177 
00179         gzVoid reuseLinks(gzBool on=FALSE) ;
00180 
00181         gzBool operator==(const gzList &right) const;
00182 
00183     protected:
00184 
00185         struct LinkItem
00186         {
00187             gzDouble        sortval;
00188             T               *item;
00189             LinkItem        *next;
00190         };
00191 
00192         gzVoid          disposeLink(LinkItem *link) ;
00193         LinkItem *      allocLink() ;
00194 
00195 
00196         LinkItem    *m_link;
00197 
00198         LinkItem    *m_last;
00199 
00200         LinkItem    *m_recycle;
00201 
00202         gzULong     m_entries;
00203 
00204         gzBool      m_reuseLinks;
00205 
00206 };
00207 
00208 
00209 //***********************************************************************
00210 
00211 template <class T> inline gzBool gzList<T>::operator==(const gzList &right) const
00212 {
00213     if(m_entries!=right.m_entries)
00214         return FALSE;
00215 
00216     LinkItem *a=m_link;
00217 
00218     LinkItem *b=right.m_link;
00219 
00220     while(a)
00221     {
00222         if(a->item!=b->item)
00223             return FALSE;
00224 
00225         a=a->next;
00226         b=b->next;
00227     }
00228     
00229     return TRUE;
00230 }
00231 
00232 template <class T> inline gzVoid gzList<T>::reuseLinks(gzBool on) 
00233 {
00234     m_reuseLinks=on;
00235 }
00236 
00237 template <class T> inline typename gzList<T>::LinkItem * gzList<T>::allocLink() 
00238 {
00239     if(m_reuseLinks && m_recycle)
00240     {
00241         LinkItem *link=m_recycle;
00242 
00243         m_recycle=m_recycle->next;
00244 
00245         return link;
00246     }
00247     return new LinkItem;
00248 }
00249 
00250 template <class T> inline gzVoid gzList<T>::disposeLink(LinkItem *link) 
00251 { 
00252     if(m_reuseLinks)
00253     {
00254         link->next=m_recycle;
00255         m_recycle=link;
00256     }
00257     else
00258         delete link;
00259 }
00260 
00261 template <class T> inline gzVoid gzList<T>::cleanLinks() 
00262 {
00263     if(m_recycle)
00264     {
00265         LinkItem *nextlink;
00266 
00267         while(m_recycle)
00268         {
00269             nextlink=m_recycle->next;
00270             delete m_recycle;
00271             m_recycle=nextlink;
00272         }
00273     }
00274 }
00275 
00276 //***********************************************************************
00277 
00278 template <class T> inline T* gzList<T>::cloneEntry(T *item) const
00279 {
00280     return item;
00281 }
00282 
00283 //***********************************************************************
00284 
00285 template <class T> inline gzULong gzList<T>::entries()  const 
00286 {
00287     return m_entries;
00288 }
00289 
00290 //***********************************************************************
00291 
00292 template <class T> inline T *gzList<T>::remove( T *item ) 
00293 {
00294     LinkItem *link=m_link;
00295     LinkItem *prevlink=0;
00296 
00297     T *retitem;
00298 
00299     while(link)
00300     {
00301         if(item==link->item)
00302         {
00303             if(!prevlink)
00304             {
00305                 m_link=link->next;
00306                 if(!m_link)
00307                     m_last=0;
00308             }
00309             else
00310             {
00311                 prevlink->next=link->next;
00312                 if(!prevlink->next)
00313                     m_last=prevlink;
00314             }
00315             retitem=link->item;
00316             disposeLink(link);
00317             m_entries--;
00318             onRemove(retitem);
00319             return retitem;
00320         }
00321         prevlink=link;
00322         link=link->next;
00323     }
00324     return 0;
00325 }
00326 
00327 //***********************************************************************
00328 
00329 template <class T> inline T *gzList<T>::removeFirst() 
00330 {
00331     if(!m_link)
00332         return 0;
00333 
00334     LinkItem *link=m_link;
00335 
00336     T *item=link->item;
00337     m_link=m_link->next;
00338     if(!m_link)
00339         m_last=0;
00340 
00341     disposeLink(link);
00342 
00343     m_entries--;
00344 
00345     onRemove(item);
00346     return item;
00347 }
00348 
00349 //***********************************************************************
00350 
00351 template <class T> inline T *gzList<T>::removeLast() 
00352 {
00353     if(!m_link)
00354         return 0;
00355 
00356     LinkItem *link=m_link;
00357 
00358     T *item=m_last->item;
00359 
00360     if(m_link==m_last)
00361     {
00362         disposeLink(m_link);
00363         m_link=0;
00364         m_last=0;
00365     }
00366     else
00367     {
00368         while(link->next!=m_last)
00369             link=link->next;
00370         disposeLink(m_last);
00371 
00372         m_last=link;
00373         m_last->next=0;
00374     }
00375 
00376     m_entries--;
00377 
00378     onRemove(item);
00379     return item;
00380 }
00381 
00382 //***********************************************************************
00383 
00384 template <class T> inline T *gzList<T>::last() const
00385 {
00386     if(!m_last)
00387         return 0;
00388     return m_last->item;
00389 }
00390 
00391 //***********************************************************************
00392 
00393 template <class T> inline T *gzList<T>::first() const
00394 {
00395     if(!m_link)
00396         return 0;
00397     return m_link->item;
00398 }
00399 
00400 //***********************************************************************
00401 
00402 template <class T> inline T *gzList<T>::operator[](gzULong i) 
00403 {
00404     if(i>=m_entries)
00405         return NULL;
00406 
00407     LinkItem *link=m_link;
00408 
00409     gzULong j;
00410 
00411     for(j=0;j<i;++j)
00412         link=link->next;
00413 
00414     return link->item;
00415 }
00416 
00417 //***********************************************************************
00418 
00419 template <class T> inline gzList<T>::gzList(gzBool reuseLinks)  : m_link(0),m_last(0),m_recycle(0),m_entries(0),m_reuseLinks(reuseLinks)
00420 {
00421 }
00422 
00423 //***********************************************************************
00424 
00425 template <class T> inline gzList<T>::~gzList() 
00426 {
00427     clear();
00428     cleanLinks();
00429 }
00430 
00431 //***********************************************************************
00432 
00433 template <class T> inline gzVoid gzList<T>::insertAt(gzULong index,T *item) 
00434 {
00435     if(index>=m_entries)
00436     {
00437         insert(item);
00438         return;
00439     }
00440 
00441     LinkItem *newlink=allocLink();
00442     newlink->sortval=0;
00443     newlink->item=item;
00444 
00445     LinkItem *pre_link=NULL;
00446     LinkItem *post_link=m_link;
00447 
00448     gzULong i;
00449 
00450     for(i=0;i<index;++i)
00451     {
00452         if(post_link)
00453         {
00454             pre_link=post_link;
00455             post_link=post_link->next;
00456         }
00457         else
00458             break;
00459     }
00460 
00461     if(pre_link)    // Not first item
00462     {
00463         newlink->next=pre_link->next;
00464         pre_link->next=newlink;
00465 
00466         if(!post_link)  // last
00467             m_last=newlink;
00468     }
00469     else            // First item
00470     {
00471         if(m_link)  // Not last
00472         {
00473             newlink->next=m_link;
00474             m_link=newlink;
00475         }
00476         else        // last
00477         {
00478             newlink->next=NULL;
00479             m_last=m_link=newlink;
00480         }
00481     }
00482     ++m_entries;
00483     onInsert(item);
00484 }
00485 
00486 //***********************************************************************
00487 
00488 template <class T> inline T * gzList<T>::removeAt(gzULong index) 
00489 {
00490     if(index>=m_entries-1)
00491     {
00492         if(index==m_entries-1)
00493             return removeLast();
00494         return NULL;
00495     }
00496 
00497     LinkItem *pre_link=NULL;
00498     LinkItem *post_link=m_link;
00499 
00500     gzULong i;
00501 
00502     for(i=0;i<index;++i)
00503     {
00504         if(post_link)
00505         {
00506             pre_link=post_link;
00507             post_link=post_link->next;
00508         }
00509         else
00510             break;
00511     }
00512 
00513     if(post_link)   // item to remove
00514     {
00515         if(pre_link)    // have previous item
00516         {
00517             if(!(pre_link->next=post_link->next))   // last item
00518                 m_last=pre_link;
00519 
00520         }
00521         else    // remove first item
00522         {
00523             m_link=post_link->next;
00524             if(!(m_link=post_link->next))   // was last item
00525                 m_last=NULL;
00526         }
00527         m_entries--;
00528 
00529         T *item=post_link->item;
00530 
00531         disposeLink(post_link);
00532 
00533         onRemove(item);
00534         return item;
00535     }
00536     else
00537         return NULL;
00538 }
00539 
00540 //***********************************************************************
00541 
00542 template <class T> inline gzVoid gzList<T>::insert( T *item) 
00543 {
00544     LinkItem *newlink=allocLink();
00545 
00546     newlink->next=0;
00547 
00548     newlink->sortval=0;
00549 
00550     if(m_last)
00551         m_last->next=newlink;
00552     else
00553         m_link=newlink;
00554 
00555     newlink->item=item;
00556     m_last=newlink;
00557 
00558     ++m_entries;
00559     onInsert(item);
00560 }
00561 
00562 //***********************************************************************
00563 
00564 template <class T> inline gzVoid gzList<T>::pre_insert( T *item) 
00565 {
00566     LinkItem *newlink=allocLink();
00567 
00568     newlink->next=m_link;
00569     newlink->sortval=0;
00570 
00571     m_link=newlink;
00572 
00573     if(!m_last)
00574         m_last=newlink;
00575 
00576     newlink->item=item;
00577 
00578     ++m_entries;
00579     onInsert(item);
00580 }
00581 
00582 //***********************************************************************
00583 template <class T> inline T * gzList<T>::findSortItem(gzDouble sortval,const T *prevItem)
00584 {
00585     const typename gzList<T>::LinkItem* link = m_link;
00586     
00587     if(prevItem)
00588     {
00589         while (link)
00590         {
00591             if (link->item == prevItem)
00592             {
00593                 link = link->next;
00594                 break;
00595             }
00596 
00597             link = link->next;
00598         }
00599     }
00600     
00601     while (link)
00602     {
00603         if (link->sortval == sortval)
00604         {
00605             return link->item;
00606         }
00607 
00608         link = link->next;
00609     }
00610 
00611     return NULL;
00612 }
00613 
00614 template <class T> inline T* gzList<T>::insert( T *item , gzDouble sortval) 
00615 {
00616     LinkItem *newlink=allocLink();
00617 
00618 
00619     newlink->item=item;
00620     newlink->sortval=sortval;
00621 
00622     onInsert(item);
00623 
00624     if(m_last)
00625     {
00626         if(m_last->sortval<sortval)
00627         {
00628 
00629             m_last->next=newlink;
00630             newlink->next=NULL;
00631             m_last=newlink;
00632             ++m_entries;
00633 
00634             return NULL;
00635         }
00636     }
00637 
00638     T *deleteitem=0;
00639 
00640     LinkItem *sortitem=m_link;
00641     LinkItem *previtem=0;
00642 
00643     while(sortitem)
00644     {
00645         if(sortitem->sortval<sortval)
00646         {
00647             if(!previtem)
00648                 previtem=sortitem;
00649             else
00650                 previtem=previtem->next;
00651             sortitem=sortitem->next;
00652         }
00653         else if(sortitem->sortval==sortval)
00654         {
00655             deleteitem=sortitem->item;
00656             sortitem->item=item;
00657             disposeLink(newlink);
00658             onRemove(deleteitem);
00659             return deleteitem;
00660         }
00661         else
00662             break;
00663     }
00664     newlink->next=sortitem;
00665     if(!previtem)
00666         m_link=newlink;
00667     else
00668         previtem->next=newlink;
00669 
00670     if(!sortitem)
00671         m_last=newlink;
00672 
00673     ++m_entries;
00674 
00675     return deleteitem;
00676 }
00677 
00678 //***********************************************************************
00679 
00680 template <class T> inline gzBool gzList<T>::post_insert( T *item , gzDouble sortval) 
00681 {
00682     LinkItem *newlink=allocLink();
00683 
00684     newlink->item=item;
00685     newlink->sortval=sortval;
00686 
00687     onInsert(item);
00688 
00689     if(m_last)
00690     {
00691         if(m_last->sortval<=sortval)
00692         {
00693             gzBool insert=(m_last->sortval==sortval);
00694 
00695             m_last->next=newlink;
00696             newlink->next=NULL;
00697             m_last=newlink;
00698             ++m_entries;
00699 
00700             return insert;
00701         }
00702     }
00703 
00704     LinkItem *sortitem=m_link;
00705     LinkItem *previtem=0;
00706 
00707 
00708     while(sortitem)
00709     {
00710         if(sortitem->sortval<=sortval)
00711         {
00712             if(!previtem)
00713                 previtem=sortitem;
00714             else
00715                 previtem=previtem->next;
00716             sortitem=sortitem->next;
00717         }
00718         else
00719             break;
00720     }
00721 
00722     newlink->next=sortitem;
00723     if(!previtem)
00724         m_link=newlink;
00725     else
00726         previtem->next=newlink;
00727 
00728     ++m_entries;
00729 
00730     if(!sortitem)
00731         m_last=newlink;
00732 
00733     if(previtem)
00734     {
00735         if(previtem->sortval==sortval)
00736             return TRUE;
00737         else
00738             return FALSE;
00739     }
00740 
00741     return FALSE;
00742 
00743 }
00744 
00745 //***********************************************************************
00746 
00747 template <class T> inline gzBool gzList<T>::pre_insert( T *item , gzDouble sortval) 
00748 {
00749     LinkItem *newlink=allocLink();
00750 
00751     newlink->item=item;
00752     newlink->sortval=sortval;
00753 
00754 
00755     onInsert(item);
00756 
00757     if(m_last)
00758     {
00759         if(m_last->sortval<sortval)
00760         {
00761 
00762             m_last->next=newlink;
00763             newlink->next=NULL;
00764             m_last=newlink;
00765             ++m_entries;
00766 
00767             return FALSE;
00768         }
00769     }
00770 
00771     LinkItem *sortitem=m_link;
00772     LinkItem *previtem=0;
00773 
00774     while(sortitem)
00775     {
00776         if(sortitem->sortval<sortval)
00777         {
00778             if(!previtem)
00779                 previtem=sortitem;
00780             else
00781                 previtem=previtem->next;
00782             sortitem=sortitem->next;
00783         }
00784         else
00785             break;
00786     }
00787 
00788     newlink->next=sortitem;
00789     if(!previtem)
00790         m_link=newlink;
00791     else
00792         previtem->next=newlink;
00793 
00794     ++m_entries;
00795 
00796     if(!sortitem)
00797         m_last=newlink;
00798     else
00799     {
00800         if(sortitem->sortval==sortval)
00801             return TRUE;
00802         else
00803             return FALSE;
00804     }
00805 
00806     return FALSE;
00807 }
00808 
00809 //***********************************************************************
00810 
00811 template <class T> inline gzList<T> & gzList<T>::operator=(const gzList &copy ) 
00812 {
00813     if(&copy==this)
00814         return *this;
00815 
00816     clear();        // rensa gammal data
00817 
00818     m_reuseLinks=copy.m_reuseLinks;
00819 
00820     LinkItem *link=copy.m_link;
00821 
00822     m_link=0;
00823     m_last=0;
00824 
00825     while(link)
00826     {
00827         LinkItem *newlink=allocLink();
00828 
00829         newlink->item=cloneEntry(link->item); // default to copy of instance
00830 
00831         onInsert(newlink->item);
00832         newlink->sortval=link->sortval;
00833         newlink->next=0;
00834 
00835         if(m_last)
00836             m_last->next=newlink;
00837         else
00838             m_link=newlink;
00839 
00840         m_last=newlink;
00841 
00842         link=link->next;
00843     }
00844     m_entries=copy.m_entries;
00845 
00846     return *this;
00847 }
00848 
00849 template <class T> inline gzList<T> & gzList<T>::operator+=(const gzList &copy ) 
00850 {
00851     if(&copy==this)
00852         return *this;
00853 
00854     LinkItem *link=copy.m_link;
00855 
00856     while(link)
00857     {
00858         LinkItem *newlink=allocLink();
00859 
00860         newlink->item=cloneEntry(link->item); // default to copy of instance
00861 
00862         onInsert(newlink->item);
00863         newlink->sortval=link->sortval;
00864         newlink->next=0;
00865 
00866         if(m_last)
00867             m_last->next=newlink;
00868         else
00869             m_link=newlink;
00870 
00871         m_last=newlink;
00872 
00873         link=link->next;
00874     }
00875     m_entries+=copy.m_entries;
00876 
00877     return *this;
00878 }
00879 
00880 //***********************************************************************
00881 
00882 template <class T> inline gzList<T>::gzList(const gzList<T> &copy) 
00883 {
00884     LinkItem *link=copy.m_link;
00885 
00886     m_link=0;
00887     m_last=0;
00888     m_recycle=0;
00889     m_reuseLinks=FALSE;
00890 
00891     while(link)
00892     {
00893         LinkItem *newlink=allocLink();
00894 
00895         newlink->item=cloneEntry(link->item); // default to copy of instance
00896 
00897         onInsert(newlink->item);
00898         newlink->sortval=link->sortval;
00899         newlink->next=0;
00900 
00901         if(m_last)
00902             m_last->next=newlink;
00903         else
00904             m_link=newlink;
00905 
00906         m_last=newlink;
00907 
00908         link=link->next;
00909     }
00910     m_entries=copy.m_entries;
00911 }
00912 
00913 //***********************************************************************
00914 
00915 template <class T> inline gzVoid gzList<T>::clearAndDestroy() 
00916 {
00917     if(m_link)
00918     {
00919         LinkItem *nextlink;
00920 
00921         while(m_link)
00922         {
00923             nextlink=m_link->next;
00924             onRemove(m_link->item);
00925             delete m_link->item;
00926             disposeLink(m_link);
00927 
00928             m_link=nextlink;
00929         }
00930         m_entries=0;
00931         m_last=0;
00932     }
00933 }
00934 
00935 //***********************************************************************
00936 
00937 template <class T> inline gzVoid gzList<T>::clear() 
00938 {
00939     if(m_link)
00940     {
00941         LinkItem *nextlink;
00942 
00943         while(m_link)
00944         {
00945             nextlink=m_link->next;
00946             onRemove(m_link->item);
00947             disposeLink(m_link);
00948 
00949             m_link=nextlink;
00950         }
00951         m_entries=0;
00952         m_last=0;
00953     }
00954 }
00955 
00956 
00957 //******************************************************************************
00958 // Template : gzListIterator
00959 //
00960 // Purpose  : Iterator for gzList
00961 //
00962 // Notes    : -
00963 //
00964 // Revision History...
00965 //
00966 // Who  Date    Description
00967 //
00968 // AMO  980601  Created
00969 //
00970 //******************************************************************************
00972 
00993 template <class T> class gzListIterator 
00994 {
00995     public:
00996 
00998         gzListIterator(gzList<T> &owner);
00999 
01001         gzListIterator(gzList<T> *owner);
01002 
01004         virtual ~gzListIterator(){};
01005 
01007 
01009         T *operator()();
01010 
01011         T *operator++(int); // postfix operator
01012 
01014 
01016         T *circulate();
01017 
01019 
01020         T *key() const;
01021 
01023         T *next() const;
01024 
01026 
01027         T *remove();
01028 
01030         gzVoid reset();
01031 
01032         gzVoid setList(gzList<T> &owner);
01033 
01035         gzDouble sortval() const;
01036 
01038         gzVoid post_insert(T *item);
01039 
01041         gzVoid pre_insert(T *item);
01042 
01043 
01044     private:
01045     
01046         typename gzList<T>::LinkItem *m_link;
01047 
01048         typename gzList<T>::LinkItem *m_prevlink;
01049 
01050         gzList<T> * m_owner;
01051 
01052         gzBool      m_circulating;
01053 
01054 };
01055 
01056 //***********************************************************************
01057 
01058 template <class T> inline gzListIterator<T>::gzListIterator(gzList<T> &owner)
01059 {
01060     m_link=0;
01061     m_prevlink=0;
01062     m_circulating=FALSE;
01063     m_owner=&owner;
01064 }
01065 
01066 template <class T> inline gzListIterator<T>::gzListIterator(gzList<T> *owner)
01067 {
01068     m_link=0;
01069     m_prevlink=0;
01070     m_circulating=FALSE;
01071     m_owner=owner;
01072 }
01073 
01074 //***********************************************************************
01075 
01076 template <class T> inline gzVoid gzListIterator<T>::setList(gzList<T> &owner)
01077 {
01078     m_link=0;
01079     m_prevlink=0;
01080     m_owner=&owner;
01081 }
01082 
01083 //***********************************************************************
01084 
01085 template <class T> inline gzDouble gzListIterator<T>::sortval() const
01086 {
01087     if(m_link)
01088         return m_link->sortval;
01089     else
01090         return 0;
01091 }
01092 
01093 //***********************************************************************
01094 
01095 template <class T> inline gzVoid gzListIterator<T>::post_insert(T *item)
01096 {
01097     if(m_link)
01098     {
01099         typename gzList<T>::LinkItem *link=m_owner->allocLink();
01100 
01101         link->next=m_link->next;
01102 
01103         link->sortval=0;
01104 
01105         link->item=item;
01106 
01107         m_link->next=link;
01108 
01109         if(m_owner->m_last==m_link)
01110             m_owner->m_last=link;
01111 
01112 
01113         m_owner->onInsert(item);
01114 
01115         ++m_owner->m_entries;
01116     }
01117 }
01118 
01119 //***********************************************************************
01120 
01121 template <class T> inline gzVoid gzListIterator<T>::pre_insert(T *item)
01122 {
01123     if(m_link)
01124     {
01125         typename gzList<T>::LinkItem *link=m_owner->allocLink();
01126 
01127         link->next=m_link;
01128 
01129         link->sortval=0;
01130 
01131         link->item=item;
01132 
01133         if(m_prevlink)
01134             m_prevlink->next=link;
01135         else
01136             m_owner->m_link=link;
01137 
01138         m_prevlink=link;
01139 
01140         m_owner->onInsert(item);
01141 
01142         ++m_owner->m_entries;
01143     }
01144 }
01145 
01146 //***********************************************************************
01147 
01148 template <class T> inline T * gzListIterator<T>::remove()
01149 {
01150     if(!m_link)
01151         return NULL;
01152 
01153     T *item=m_link->item;
01154 
01155     typename gzList<T>::LinkItem *link;
01156 
01157     if(!m_link->next)
01158         m_owner->m_last=m_prevlink;
01159 
01160     link=m_link->next;
01161 
01162     if(m_prevlink)
01163         m_prevlink->next=link;
01164     else
01165         m_owner->m_link=link;
01166 
01167     m_owner->onRemove(m_link->item);
01168     m_owner->disposeLink(m_link);
01169     m_owner->m_entries--;
01170 
01171     m_link=m_prevlink;
01172 
01173     return item;
01174 }
01175 
01176 //***********************************************************************
01177 
01178 template <class T> inline gzVoid gzListIterator<T>::reset()
01179 {
01180     m_link=0;
01181     m_prevlink=0;
01182     m_circulating=FALSE;
01183 }
01184 
01185 //***********************************************************************
01186 
01187 template <class T> inline T *gzListIterator<T>::operator()()
01188 {
01189     if(m_prevlink=m_link)
01190         m_link=m_link->next;
01191     else
01192         m_link=m_owner->m_link;
01193 
01194     if(m_link)
01195         return m_link->item;
01196     else
01197         return NULL;
01198 }
01199 
01200 //***********************************************************************
01201 
01202 template <class T> inline T *gzListIterator<T>::operator++(int)
01203 {
01204     return operator()();
01205 }
01206 
01207 //***********************************************************************
01208 
01209 template <class T> inline T *gzListIterator<T>::circulate()
01210 {
01211     m_circulating=TRUE;
01212 
01213     m_prevlink=m_link;
01214 
01215     if(m_link)
01216         m_link=m_link->next;
01217 
01218     if(!m_link)
01219     {
01220         m_link=m_owner->m_link;
01221         m_prevlink=0;
01222     }
01223 
01224     if(m_link)
01225         return m_link->item;
01226     else
01227         return NULL;
01228 }
01229 
01230 //***********************************************************************
01231 
01232 template <class T> inline T *gzListIterator<T>::key() const
01233 {
01234     if(m_link)
01235         return m_link->item;
01236     else
01237         return NULL;
01238 }
01239 
01240 //***********************************************************************
01241 
01242 template <class T> inline T *gzListIterator<T>::next() const
01243 {
01244     if(m_link)
01245     {
01246         if(m_link->next)
01247             return m_link->next->item;
01248         else if(m_circulating)
01249             return m_owner->m_link->item;
01250     }
01251     return NULL;
01252 }
01253 
01254 //******************************************************************************
01255 // Template : gzListConstIterator
01256 //                                  
01257 // Purpose  : Constant Iterator for gzList
01258 //                                  
01259 // Notes    : -
01260 //                                  
01261 // Revision History...                          
01262 //                                  
01263 // Who  Date    Description                     
01264 //                                  
01265 // AMO  040301  Created 
01266 //                                  
01267 //******************************************************************************
01269 
01285 template <class T> class gzListConstIterator 
01286 {
01287     public:
01288 
01290         gzListConstIterator(const gzList<T> &owner);
01291 
01293         virtual ~gzListConstIterator(){};
01294 
01296 
01298         T *operator()();
01299 
01300         T *operator++(int); // postfix operator
01301 
01303 
01305         T *circulate();
01306 
01308 
01309         T *key() const;
01310 
01312         T *next() const;
01313 
01315         gzVoid reset();
01316 
01318         gzDouble sortval() const;
01319 
01320 
01321     private:
01322     
01323         typename gzList<T>::LinkItem *m_link;
01324 
01325         typename gzList<T>::LinkItem *m_prevlink;
01326 
01327         const gzList<T> *   m_owner;
01328 
01329         gzBool      m_circulating;
01330 
01331 };
01332 
01333 //***********************************************************************
01334 
01335 template <class T> inline gzBool gzList<T>::contains(const T *item) const 
01336 {
01337     const typename gzList<T>::LinkItem* link = m_link;
01338         
01339     while (link)
01340     {
01341         if (link->item == item)
01342         {
01343             return TRUE;
01344         }
01345 
01346         link = link->next;
01347     }
01348     
01349     return FALSE;
01350 }
01351 
01352 //***********************************************************************
01353 
01354 template <class T> inline gzListConstIterator<T>::gzListConstIterator(const gzList<T> &owner)
01355 {
01356     m_link=0;
01357     m_prevlink=0;
01358     m_circulating=FALSE;
01359     m_owner=&owner;
01360 }
01361 
01362 //***********************************************************************
01363 
01364 template <class T> inline gzDouble gzListConstIterator<T>::sortval() const
01365 {
01366     if(m_link)
01367         return m_link->sortval;
01368     else
01369         return 0;
01370 }
01371 
01372 //***********************************************************************
01373 
01374 template <class T> inline gzVoid gzListConstIterator<T>::reset()
01375 {
01376     m_link=0;
01377     m_prevlink=0;
01378     m_circulating=