Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

t_list.h

00001 /* liblookdb: t_list.h - List looking like a cut down  stl deque 
00002     Copyright (C) 1998-2001 LOOK Systems
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Lesser General Public
00006     License as published by the Free Software Foundation; either
00007     version 2.1 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this library; if not, write to the Free Software
00016     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 */
00018 #ifndef LIBLOOKDB_T_LIST_H
00019 #define LIBLOOKDB_T_LIST_H
00020 
00021 // $Id: t_list.h,v 1.6 2001/07/04 15:53:22 clive Exp $
00022 
00023 #include "lookcompileropts.h"
00024 
00025 #include "stddef.h"
00026 
00027 namespace look {
00028 
00029 #ifdef WIN32
00030 #pragma warning( disable : 4284 )
00031 #pragma warning( disable : 4786 )
00032 #pragma warning( disable : 4251 )
00033 #endif
00034 
00036 
00044 template<class tBody>
00045 class LookTLList
00046 {
00047 protected:
00048         struct ListItem
00049         {
00050         public:
00051                 ListItem( const tBody &theItem,
00052                         ListItem *thePrevious = NULL,
00053                         ListItem *theNext = NULL )
00054                         : itsPrevious( thePrevious ),
00055                         itsNext( theNext ),
00056                         itsItem( theItem )
00057                 {}
00058                 
00059                 ListItem *itsPrevious;
00060                 ListItem *itsNext;
00061                 tBody itsItem;
00062         };
00063 
00064 protected:
00065 
00066         ListItem *itsFirstItem;
00067         ListItem *itsLastItem;
00068         ListItem *itsMemoryItem;   // mutable?  // Not on cxx5 - xian
00069         size_t itsMemoryItemNumber;// mutable?
00070         size_t itsNumberOfItems;
00071 
00072         // implemented functions
00073 
00074         // Appends the given tBody to the end of the list.
00075         void append( const tBody &a )
00076         {
00077                 ListItem *aNewItem = new ListItem( a,
00078                         itsLastItem,
00079                         NULL );
00080                 if( itsLastItem != NULL )
00081                 {
00082                         itsLastItem -> itsNext = aNewItem;
00083                         itsLastItem = aNewItem;
00084                 }
00085                 else
00086                 {
00087                         itsMemoryItem = itsFirstItem = itsLastItem = aNewItem;
00088                         itsMemoryItemNumber = 0;
00089                 }
00090                 itsNumberOfItems++;
00091         }
00092 
00093         // prepends the given tBody to the end of the list.
00094         void prepend( const tBody &a )
00095         {
00096                 ListItem *aNewItem = new ListItem( a,
00097                         NULL,
00098                         itsFirstItem );
00099                 if( itsFirstItem != NULL )
00100                 {
00101                         itsFirstItem -> itsPrevious = aNewItem;
00102                         itsFirstItem = aNewItem;
00103                 }
00104                 else
00105                 {
00106                         itsFirstItem = itsLastItem = aNewItem;
00107                 }
00108                 
00109                 itsMemoryItem = aNewItem;
00110                 itsMemoryItemNumber = 0;
00111                 itsNumberOfItems++;
00112         }
00113 
00114         void InvalidateMemoryIterator( void )
00115         {
00116                 itsMemoryItem = itsFirstItem;
00117                 itsMemoryItemNumber = 0;
00118         }
00119 
00120         // Move the list iterator to the given index.
00121         void MoveMemoryIteratorToItemAt( size_t i ) const
00122         {
00123                 // cast away const so we can access our memory bits
00124                 LookTLList<tBody> * const localThis = (LookTLList<tBody> * const) this;
00125 
00126                 if( itsNumberOfItems == 0 || itsMemoryItemNumber == i
00127                         || itsNumberOfItems < i )
00128                 {
00129                         return;
00130                 }
00131                 
00132                 if( i < itsNumberOfItems - i )
00133                 {
00134                         if( itsMemoryItemNumber > i && itsMemoryItemNumber - i > i )
00135                         {
00136                                 localThis->itsMemoryItemNumber = 0;
00137                                 localThis->itsMemoryItem = itsFirstItem;
00138                         }
00139                 }
00140                 else
00141                 {
00142                         if( itsMemoryItemNumber < i && i - itsMemoryItemNumber > i )
00143                         {
00144                                 localThis->itsMemoryItemNumber = itsNumberOfItems - 1;
00145                                 localThis->itsMemoryItem = itsLastItem;
00146                         }
00147                 }
00148                 
00149                 if( itsMemoryItemNumber < i )
00150                 {
00151                         size_t Count;
00152                         for( Count = itsMemoryItemNumber; Count < i; Count++ )
00153                         {
00154                                 localThis->itsMemoryItem = itsMemoryItem->itsNext;
00155                         }
00156                 }
00157                 else
00158                 {
00159                         size_t Count;
00160                         for( Count = itsMemoryItemNumber; Count > i; Count-- )
00161                         {
00162                                 localThis->itsMemoryItem = itsMemoryItem->itsPrevious;
00163                         }
00164                 }
00165                 localThis->itsMemoryItemNumber = i;
00166         }
00167 
00168 public:
00169 
00170         // ======================================
00171 
00172         // iterator things
00173         // the iterator bypasses the list's idea of iterators
00174 
00175         class iterator;
00176         friend class iterator;
00177 
00179         class iterator
00180         {
00181         public:
00182                 friend class LookTLList<tBody>;
00183 
00184                 iterator()
00185                         : itsItem( NULL ),
00186                         itsList( NULL )
00187                 {
00188                 }
00189 
00190                 ~iterator()
00191                 {
00192                 }
00193 
00194 
00195                 iterator( const LookTLList<tBody>* theList, ListItem* theItem )
00196                         : itsItem( theItem ),
00197                         itsList( (LookTLList<tBody>*) theList )
00198                 {
00199                 }
00200 
00201                 iterator& operator++()
00202                 {
00203                         if( itsItem )
00204                         {
00205                                 itsItem = itsItem->itsNext;
00206                         }
00207                         return *this;
00208                 }
00209 
00210                 iterator operator++(int)
00211                 {
00212                         iterator temp( *this );
00213                         if( itsItem )
00214                         {
00215                                 itsItem = itsItem->itsNext;
00216                         }
00217                         return temp;
00218                 }
00219 
00220                 iterator& operator--()
00221                 {
00222                         if( itsItem )
00223                         {
00224                                 itsItem = itsItem->itsPrevious;
00225                         }
00226                         else if( itsList )
00227                         {
00228                                 itsItem = itsList->itsLastItem;
00229                         }
00230 
00231                         return *this;
00232                 }
00233 
00234                 iterator operator--(int)
00235                 {
00236                         iterator temp( *this );
00237                         if( itsItem )
00238                         {
00239                                 itsItem = itsItem->itsPrevious;
00240                         }
00241                         else if( itsList )
00242                         {
00243                                 itsItem = itsList->itsLastItem;
00244                         }
00245                         return temp;
00246                 }
00247                 
00248                 iterator& operator+=( size_t theChange )
00249                 {
00250                         for( size_t loop = 0; loop < theChange; loop++ )
00251                         {
00252                                 ++(*this);
00253                         }
00254                         return *this;
00255                 }
00256 
00257                 iterator& operator-=( size_t theChange )
00258                 {
00259                         for( size_t loop = 0; loop < theChange; loop++ )
00260                         {
00261                                 --(*this);
00262                         }
00263                         return *this;
00264                 }
00265 
00266                 bool operator!=( const iterator& anIter )
00267                 {
00268                         return( itsItem != anIter.itsItem );
00269                 }
00270 
00271                 bool operator==( const iterator& anIter )
00272                 {
00273                         return( itsItem == anIter.itsItem );
00274                 }
00275 
00276         // the useful access ops
00277                 tBody& operator*() const
00278                 {
00279                         return itsItem->itsItem;
00280                 }
00281 
00282                 tBody* operator->() const
00283                 {
00284                         return (&**this);
00285                 }
00286 
00287         protected:
00288                 ListItem* itsItem;
00289                 LookTLList<tBody>* itsList;
00290         };
00291 
00292         typedef iterator const_iterator;
00293 
00294         class reverse_iterator;
00295         friend class reverse_iterator;
00296 
00298         class reverse_iterator
00299         {
00300         public:
00301                 friend class LookTLList<tBody>;
00302 
00303                 reverse_iterator()
00304                         : itsItem( NULL ),
00305                         itsList( NULL )
00306                 {
00307                 }
00308 
00309                 ~reverse_iterator()
00310                 {
00311                 }
00312 
00313                 reverse_iterator( const LookTLList<tBody>* theList, ListItem* theItem )
00314                         : itsItem( theItem ),
00315                         itsList( (LookTLList<tBody>*) theList )
00316                 {
00317                 }
00318 
00319                 reverse_iterator& operator++()
00320                 {
00321                         if( itsItem )
00322                         {
00323                                 itsItem = itsItem->itsPrevious;
00324                         }
00325                         else if( itsList )
00326                         {
00327                                 itsItem = itsList->itsLastItem;
00328                         }
00329                         return *this;
00330                 }
00331 
00332                 reverse_iterator operator++(int)
00333                 {
00334                         reverse_iterator temp( *this );
00335                         if( itsItem )
00336                         {
00337                                 itsItem = itsItem->itsPrevious;
00338                         }
00339                         else if( itsList )
00340                         {
00341                                 itsItem = itsList->itsLastItem;
00342                         }
00343                         return temp;
00344                 }
00345 
00346                 reverse_iterator& operator--()
00347                 {
00348                         if( itsItem )
00349                         {
00350                                 itsItem = itsItem->itsNext;
00351                         }
00352 
00353                         return *this;
00354                 }
00355 
00356                 reverse_iterator operator--(int)
00357                 {
00358                         reverse_iterator temp( *this );
00359                         if( itsItem )
00360                         {
00361                                 itsItem = itsItem->itsNext;
00362                         }
00363                         return temp;
00364                 }
00365 
00366                 reverse_iterator& operator+=( size_t theChange )
00367                 {
00368                         for( size_t loop = 0; loop < theChange; loop++ )
00369                         {
00370                                 ++(*this);
00371                         }
00372                         return *this;
00373                 }
00374 
00375                 reverse_iterator& operator-=( size_t theChange )
00376                 {
00377                         for( size_t loop = 0; loop < theChange; loop++ )
00378                         {
00379                                 --(*this);
00380                         }
00381                         return *this;
00382                 }
00383 
00384                 bool operator!=( const reverse_iterator& anIter )
00385                 {
00386                         return( itsItem != anIter.itsItem );
00387                 }
00388 
00389                 bool operator==( const reverse_iterator& anIter )
00390                 {
00391                         return( itsItem == anIter.itsItem );
00392                 }
00393                 
00394                 // the useful access ops
00395                 tBody& operator*() const
00396                 {
00397                         if( itsItem )
00398                         {
00399                                 return itsItem->itsPrevious->itsItem;
00400                         }
00401                         else
00402                         {
00403                                 return itsList->itsLastItem->itsItem;
00404                         }
00405                 }
00406 
00407                 tBody* operator->() const
00408                 {
00409                         return (&**this);
00410                 }
00411 
00412         protected:
00413                 ListItem* itsItem;
00414                 LookTLList<tBody>* itsList;
00415         };
00416 
00417         typedef reverse_iterator const_reverse_iterator;
00418 
00420         reverse_iterator rbegin( void ) const
00421         {
00422                 return reverse_iterator( this, NULL );
00423         }
00424 
00426         reverse_iterator rend( void ) const
00427         {
00428                 return reverse_iterator( this, itsFirstItem );
00429         }
00430 
00432         iterator begin( void ) const
00433         {
00434                 return iterator( this, itsFirstItem );
00435         }
00436 
00438         iterator end( void ) const
00439         {
00440                 return iterator( this, NULL );
00441         }
00442 
00444 
00447         iterator insert( iterator anIt, const tBody& theThing )
00448         {
00449                 if( anIt == end() )
00450                 {
00451                         append( theThing );
00452                         return (--end());  // apologies for prefix--
00453                 }
00454                 else if( anIt == begin() )
00455                 {
00456                         prepend( theThing );
00457                         return begin();
00458                 }
00459                 
00460                 ListItem* aCurrentItem = anIt.itsItem;
00461 
00462                 ListItem *aNewItem = new ListItem( theThing,
00463                         aCurrentItem->itsPrevious,
00464                         aCurrentItem );
00465                 if( aCurrentItem->itsPrevious != NULL)
00466                 {
00467                         aCurrentItem->itsPrevious->itsNext = aNewItem;
00468                 }
00469 
00470                 aCurrentItem->itsPrevious = aNewItem;
00471                 
00472                 itsNumberOfItems++;
00473                 InvalidateMemoryIterator();
00474 
00475                 return iterator( this, aNewItem );
00476         }
00477 
00479         iterator erase( iterator anIt )
00480         {
00481                 ListItem* aCurrentItem = anIt.itsItem;
00482 
00483                 if( aCurrentItem->itsPrevious != NULL )
00484                 {
00485                         aCurrentItem->itsPrevious->itsNext =
00486                                 aCurrentItem->itsNext;
00487                 }
00488                 else
00489                 {
00490                         itsFirstItem = aCurrentItem->itsNext;
00491                 }
00492                 if( aCurrentItem->itsNext != NULL )
00493                 {
00494                         aCurrentItem->itsNext->itsPrevious =
00495                                 aCurrentItem->itsPrevious;
00496                 }
00497                 else
00498                 {
00499                         itsLastItem = aCurrentItem->itsPrevious;
00500                 }
00501                 
00502                 iterator returnIt( this, aCurrentItem->itsNext );
00503 
00504                 delete aCurrentItem;
00505                 
00506                 itsNumberOfItems--;
00507                 InvalidateMemoryIterator();
00508 
00509                 return returnIt;
00510         }
00511 
00513         iterator erase(iterator first, iterator last)
00514         {
00515                 while( first != last )
00516                 {
00517                         first = erase( first );
00518                 }
00519                 return first;
00520         }
00521 
00522 // Clear the list calling the destructor for the tBodys.
00524         void clear( void )
00525         {
00526                 erase( begin(), end() );
00527         }
00528 
00530         LookTLList()
00531                 :       itsFirstItem( NULL ),
00532                 itsLastItem( NULL ),
00533                 itsMemoryItem( NULL ),
00534                 itsMemoryItemNumber( 0 ),
00535                 itsNumberOfItems( 0 )
00536         {
00537         }
00538         
00540         ~LookTLList()
00541         {
00542                 clear();
00543         }
00544         
00545         // STL named methods
00546 
00548         void push_back( const tBody &a )
00549         {
00550                 append( a );
00551         }
00552 
00554         void push_front( const tBody &a )
00555         {
00556                 prepend( a );
00557         }
00558 
00560         void pop_back( void )
00561         {
00562                 erase( --end() );
00563         }
00564 
00566         void pop_front( void )
00567         {
00568                 erase( begin() );
00569         }
00570 
00572         tBody& back( void )
00573         {
00574                 return (*(--end()));
00575         }
00576 
00578         tBody& front( void )
00579         {
00580                 return (*begin());
00581         }
00582 
00584 
00589         void pushIfAbsent( const tBody &a )
00590         {
00591                 iterator anIter = begin();
00592                 for (; anIter != end(); anIter++) {
00593                         if (*anIter == a) return;       // do nothing if found
00594                 }
00595                 push_back(a);
00596         }
00597 
00598         // Return the tBody at the specified position.
00599         // 'memory' bits to avoid unnecessary list traversal
00601 
00608         tBody& at( size_t i ) const
00609         {
00610                 MoveMemoryIteratorToItemAt( i );
00611                 return itsMemoryItem->itsItem;
00612         }
00613 
00615         size_t size( void ) const
00616         {
00617                 return itsNumberOfItems;
00618         }
00619 
00621         tBody& operator[]( size_t i ) const
00622         {
00623                 return at( i );
00624         }
00625 
00627         void assign( const_iterator first, const_iterator last )
00628         {
00629                 clear();
00630                 for( ; first != last; first++ )
00631                 {
00632                         push_back( *first );
00633                 }
00634         }
00635 
00637         bool empty( void )
00638         {
00639                 return( itsNumberOfItems == 0 );
00640         }
00641 
00642         typedef tBody value_type;
00643 };
00644 
00645 
00646 } // end of "look" namespace
00647 #endif

Generated at Thu Jan 17 12:53:06 2002 for liblookdb by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001