• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

spl/collection/List.h

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL 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
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #ifndef _tlist_h
00018 #define _tlist_h
00019 
00020 #include <spl/types.h>
00021 #include <spl/Debug.h>
00022 
00023 #include <spl/collection/Array.h>
00024 #include <spl/Compare.h>
00025 #include <spl/Exception.h>
00026 #include <spl/collection/IEnumerable.h>
00027 #include <spl/IIterator.h>
00028 #include <spl/math/Math.h>
00029 #include <spl/Memory.h>
00030 #include <spl/RefCountPtr.h>
00031 
00037 template<typename T>
00038 class _listnode
00039 {
00040 public:
00041         _listnode *next;
00042         _listnode *prev;
00043         T data;
00044 };
00045 
00047 template<typename T>
00048 class List : public IEnumerable<T>
00049 {
00050 private:
00051         inline void _Init()
00052         {
00053                 m_head.data = T();
00054                 m_head.next = &m_tail;
00055                 m_head.prev = NULL;
00056                 m_tail.data = T();
00057                 m_tail.next = NULL;
00058                 m_tail.prev = &m_head;
00059                 m_count = 0;
00060         }
00061 
00062 protected:
00063         _listnode<T> m_head;
00064         _listnode<T> m_tail;
00065         int m_count;
00066 
00067 public:
00069         class Iterator : public IIterator<T>
00070         {
00071                 friend class List<T>;
00072 
00073         private:
00074                 _listnode<T> *m_current;
00075 
00076         public:
00077                 Iterator()
00078                 : m_current(NULL)
00079                 {
00080                 }
00081 
00082                 Iterator(_listnode<T> *head)
00083                 : m_current(head)
00084                 {
00085                 }
00086 
00087                 Iterator(const Iterator& li)
00088                 : m_current(li.m_current)
00089                 {
00090                 }
00091 
00092                 virtual bool Next( )
00093                 {
00094                         if (NULL == m_current || NULL == m_current->next)
00095                         {
00096                                 // m_current is the tail node
00097                                 return false;
00098                         }
00099                         m_current = m_current->next;
00100                         if (NULL == m_current->next)
00101                         {
00102                                 // m_current is the tail node
00103                                 return false;
00104                         }
00105 
00106                         ASSERT_MEM( m_current, sizeof( _listnode<T> ) );
00107                         return true;
00108                 }
00109 
00110                 virtual bool Prev( )
00111                 {
00112                         if (NULL == m_current || NULL == m_current->prev)
00113                         {
00114                                 // Head
00115                                 return false;
00116                         }
00117                         m_current = m_current->prev;
00118                         if (NULL == m_current->prev)
00119                         {
00120                                 // Head
00121                                 return false;
00122                         }
00123                         return true;
00124                 }
00125 
00126                 virtual T Current()
00127                 {
00128                         ASSERT_MEM( m_current, sizeof( _listnode<T> ) );
00129                         return m_current->data;
00130                 }
00131 
00132                 virtual T& CurrentRef()
00133                 {
00134                         ASSERT_MEM( m_current, sizeof( _listnode<T> ) );
00135                         return m_current->data;
00136                 }
00137         };
00138         
00139         List()
00140         {
00141                 _Init();
00142         }
00143 
00144         List( const List<T>& list )
00145         {
00146                 _Init();
00147 
00148                 _listnode<T> *node = list.m_head.next;
00149                 while ( node != &list.m_tail )
00150                 {
00151                         ASSERT_MEM( node, sizeof( _listnode<T> ) );
00152                         Add( node->data );
00153                         node = node->next;
00154                 }
00155         }
00156 
00157         ~List()
00158         {
00159                 Clear();
00160         }
00161 
00162         List<T>& operator =( const List<T>& list )
00163         {
00164                 Clear();
00165 
00166                 _listnode<T> *node = list.m_head.next;
00167                 while ( node != &list.m_tail )
00168                 {
00169                         Add( node->data );
00170                         node = node->next;
00171                 }
00172                 return *this;
00173         }
00174 
00175         bool IsEmpty(  ) const
00176         {
00177                 return m_head.next == &m_tail;
00178         }
00179 
00180         void Clear(  )
00181         {
00182                 _listnode<T> *np;
00183                 _listnode<T> *npnext;
00184 
00185                 np = m_head.next;
00186 
00187                 while ( np != &m_tail )
00188                 {
00189                         ASSERT_MEM( np, sizeof( _listnode<T> ) );
00190                         npnext = np->next;
00191                         delete np;
00192                         np = npnext;
00193                 }
00194                 m_head.next = &m_tail;
00195                 m_count = 0;
00196                 ASSERT( IsEmpty(  ) );
00197         }
00198 
00199         void Add( T data )
00200         {
00201                 _listnode<T> *np;
00202                 np = new _listnode<T>();
00203                 np->data = data;
00204                 np->next = m_head.next;
00205                 np->prev = &m_head;
00206                 m_head.next->prev = np;
00207                 m_head.next = np;
00208                 m_count++;
00209         }
00210 
00211         inline Iterator Begin()
00212         {
00213                 return Iterator(&m_head);
00214         }
00215 
00216         T& ElementAt( const int index ) const
00217         {
00218                 int count = 0;
00219                 _listnode<T> *np;
00220 
00221                 np = m_head.next;
00222                 while ( np != &m_tail && count < index )
00223                 {
00224                         np = np->next;
00225                         count++;
00226                 }
00227                 if ( np == &m_tail )
00228                 {
00229                         throw IndexOutOfBoundsException();
00230                 }
00231                 return np->data;
00232         }
00233 
00234         inline T& operator[] (const int idx) const
00235         {
00236                 return ElementAt(idx);
00237         }
00238 
00239         void RemoveCurrent( Iterator& iter )
00240         {
00241                 _listnode<T> *newcur = iter.m_current->prev;
00242                 ASSERT( iter.m_current != &m_head && iter.m_current != &m_tail && iter.m_current != NULL );
00243                 iter.m_current->prev->next = iter.m_current->next;
00244                 iter.m_current->next->prev = iter.m_current->prev;
00245                 ASSERT_MEM( iter.m_current, sizeof( _listnode<T> ) );
00246                 delete iter.m_current;
00247                 iter.m_current = newcur;
00248                 m_count--;
00249         }
00250 
00251         T Pop()
00252         {
00253                 _listnode<T> *cur = m_head.next;
00254                 ASSERT( cur != &m_tail );
00255                 m_head.next = cur->next;
00256                 cur->next->prev = &m_head;
00257                 T data = cur->data;
00258                 m_count--;
00259                 delete cur;
00260                 return data;
00261         }
00262 
00263         T Peek() const
00264         {
00265                 _listnode<T> *cur = m_head.next;
00266                 if( cur == &m_tail )
00267                 {
00268                         return NULL;
00269                 }
00270                 return cur->data;
00271         }
00272 
00273         T& PeekRef() const
00274         {
00275                 _listnode<T> *cur = m_head.next;
00276                 if( cur == &m_tail )
00277                 {
00278                         return T();
00279                 }
00280                 return cur->data;
00281         }
00282 
00283         T Tail() const
00284         {
00285                 _listnode<T> *cur = m_tail.prev;
00286                 if( cur == &m_head )
00287                 {
00288                         return T();
00289                 }
00290                 return cur->data;
00291         }
00292 
00293         T& TailRef() const
00294         {
00295                 _listnode<T> *cur = m_tail.prev;
00296                 if( cur == &m_head )
00297                 {
00298                         return T();
00299                 }
00300                 return cur->data;
00301         }
00302 
00303         void RemoveTail(  )
00304         {
00305                 _listnode<T> *cur = m_tail.prev;
00306                 ASSERT( cur != &m_head && cur != &m_tail && cur != NULL );
00307                 cur->prev->next = cur->next;
00308                 cur->next->prev = cur->prev;
00309                 ASSERT_MEM( cur, sizeof( _listnode<T> ) );
00310                 delete cur;
00311                 m_count--;
00312         }
00313 
00314         void Remove( const T& data )
00315         {
00316                 int count = 0;
00317                 _listnode<T> *np;
00318 
00319                 np = m_head.next;
00320                 while ( np != &m_tail )
00321                 {
00322                         if ( Compare::Equals(data, np->data) )
00323                         {
00324                                 np->prev->next = np->next;
00325                                 np->next->prev = np->prev;
00326                                 ASSERT_MEM( np, sizeof( _listnode<T> ) );
00327                                 delete np;
00328                                 m_count--;
00329                                 return;
00330                         }
00331                         np = np->next;
00332                         count++;
00333                 }
00334         }
00335 
00336         inline int Count(  ) const
00337         {
00338                 return m_count;
00339         }
00340 
00341         RefCountPtr<Array<T> > ToArray() const
00342         {
00343                 RefCountPtr<Array<T> > ap(new Array<T>(m_count));
00344 
00345                 Iterator iter = Begin();
00346                 int pos = 0;
00347                 while (iter.Next())
00348                 {
00349                         ap->SetElementAt(pos++, iter.Current());
00350                 }
00351                 return ap;
00352         }
00353 
00354 #ifdef DEBUG
00355         void ValidateMem() const
00356         {
00357                 _listnode<T> *np = m_head.next;
00358                 while ( np != &m_tail )
00359                 {
00360                         ASSERT_MEM( np, sizeof(_listnode<T>) );
00361                         ValidateType( np->data );
00362                         np = np->next;
00363                 }
00364                 ValidateType(m_head.data);
00365                 ValidateType(m_tail.data);
00366         }
00367 
00368         void CheckMem() const
00369         {
00370                 _listnode<T> *np = m_head.next;
00371                 while ( np != &m_tail )
00372                 {
00373                         DEBUG_NOTE_MEM_ALLOCATION( np );
00374                         ValidateType( np->data );
00375                         np = np->next;
00376                 }
00377                 ValidateType(m_head.data);
00378                 ValidateType(m_tail.data);
00379         }
00380 #else
00381         inline void ValidateMem() const {}
00382         inline void CheckMem() const {}
00383 #endif
00384 
00385 protected:
00386         virtual RefCountPtr<IIterator<T> > IteratorPtr()
00387         {
00388                 return RefCountPtr<IIterator<T> >(new Iterator(&m_head));
00389         }
00390 };
00391 
00392 REGISTER_TYPEOF( 300, List<char> );
00393 REGISTER_TYPEOF( 301, List<byte> );
00394 REGISTER_TYPEOF( 302, List<int16> );
00395 REGISTER_TYPEOF( 303, List<uint16> );
00396 REGISTER_TYPEOF( 304, List<int32> );
00397 REGISTER_TYPEOF( 305, List<uint32> );
00398 REGISTER_TYPEOF( 306, List<int64> );
00399 REGISTER_TYPEOF( 307, List<uint64> );
00400 REGISTER_TYPEOF( 308, List<float32> );
00401 REGISTER_TYPEOF( 309, List<float64> );
00402 
00403 REGISTER_TYPEOF( 310, List<BigInteger> );
00404 REGISTER_TYPEOF( 311, List<Char> );
00405 REGISTER_TYPEOF( 312, List<Date> );
00406 REGISTER_TYPEOF( 313, List<DateTime> );
00407 REGISTER_TYPEOF( 314, List<Decimal> );
00408 REGISTER_TYPEOF( 315, List<Double> );
00409 REGISTER_TYPEOF( 316, List<Int32> );
00410 REGISTER_TYPEOF( 317, List<Int64> );
00411 REGISTER_TYPEOF( 318, List<Null> );
00412 REGISTER_TYPEOF( 319, List<String> );
00413 REGISTER_TYPEOF( 320, List<StringPtr> );
00414 REGISTER_TYPEOF( 321, List<UInt32> );
00415 REGISTER_TYPEOF( 322, List<UInt64> );
00416 REGISTER_TYPEOF( 323, List<Undefined> );
00417 
00420 #endif