00001 #ifndef GSGL_DATA_LIST_H
00002 #define GSGL_DATA_LIST_H
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #include "data/data.hpp"
00038 #include "data/iterable.hpp"
00039 #include "data/indexable.hpp"
00040 #include "data/exception.hpp"
00041 
00042 namespace gsgl
00043 {
00044 
00045     namespace data
00046     {
00047 
00048         template <typename T>
00049         class list_iterator;
00050 
00051     
00052 
00053 
00054         
00055         template <typename T>
00056         class list
00057             : public data_object, public iterable<T, list_iterator<T> >, public indexable<T, gsgl::index_t>
00058         {
00059             friend class list_iterator<T>;
00060 
00061         protected:
00062         
00063             struct list_node
00064             {
00065                 T item;
00066                 list_node *prev, *next;
00067                 
00068                 list_node(const T & item, list_node *prev = 0, list_node *next = 0) 
00069                     : item(item), prev(prev), next(next) {}
00070             }; 
00071             
00072             gsgl::index_t count;
00073             list_node *head, *tail;
00074             
00075         public:
00076             list();
00077             list(const list &);
00078             list & operator= (const list &);
00079             virtual ~list();
00080             
00081             const T & get_head() const;
00082             T & get_head();
00083 
00084             const T & get_tail() const;
00085             T & get_tail();
00086 
00087             bool operator== (const list &) const;
00088 
00089 
00090 
00091             virtual gsgl::index_t size() const;
00092             virtual void clear();
00093 
00094             
00095 
00096 
00097             virtual bool contains_index(const gsgl::index_t &) const;
00098             virtual const T & item(const gsgl::index_t &) const;
00099             virtual T & item(const gsgl::index_t &);
00100 
00101             
00102 
00103 
00104 
00105             virtual void append(const T &);
00106             using iterable<T, list_iterator<T> >::append;
00107             virtual void insert(const iterator &, const T &);
00108             virtual void remove(const iterator &);
00109 
00110         }; 
00111 
00112 
00113 
00114 
00115         template <typename T> 
00116         list<T>::list() 
00117             : data_object(), iterable<T, list_iterator<T> >(), indexable<T, gsgl::index_t>(), 
00118               count(0), head(0), tail(0)
00119         {
00120         } 
00121 
00122         
00123         template <typename T> 
00124         list<T>::list(const list & l) 
00125             : data_object(), iterable<T, list_iterator<T> >(), indexable<T, gsgl::index_t>(l), 
00126               count(0), head(0), tail(0)
00127         {
00128             for (list_node *cur = l.head; cur; cur = cur->next)
00129                 append(cur->item);
00130         } 
00131 
00132         
00133         template <typename T> 
00134         list<T> & list<T>::operator= (const list & l)
00135         {
00136             clear();
00137             for (list_node *cur = l.head; cur; cur = cur->next)
00138                 append(cur->item);
00139             return *this;
00140         } 
00141 
00142         
00143         template <typename T> 
00144         list<T>::~list()
00145         {
00146             clear();
00147         } 
00148         
00149 
00150         template <typename T>
00151         const T & list<T>::get_head() const
00152         {
00153             if (head)
00154                 return head->item;
00155             else
00156                 throw memory_exception(__FILE__, __LINE__, L"Cannot get the head of an empty list.");
00157         } 
00158 
00159 
00160         template <typename T>
00161         T & list<T>::get_head()
00162         {
00163             if (head)
00164                 return head->item;
00165             else
00166                 throw memory_exception(__FILE__, __LINE__, L"Cannot get the head of an empty list.");
00167         } 
00168 
00169 
00170         template <typename T>
00171         const T & list<T>::get_tail() const
00172         {
00173             if (tail)
00174                 return tail->item;
00175             else
00176                 throw memory_exception(__FILE__, __LINE__, L"Cannot get the tail of an empty list.");
00177         } 
00178 
00179 
00180         template <typename T>
00181         T & list<T>::get_tail()
00182         {
00183             if (tail)
00184                 return tail->item;
00185             else
00186                 throw memory_exception(__FILE__, __LINE__, L"Cannot get the tail of an empty list.");
00187         } 
00188 
00189 
00190         template <typename T>
00191         bool list<T>::operator== (const list<T> & l) const
00192         {
00193             list<T>::const_iterator a = this->iter();
00194             list<T>::const_iterator b = l.iter();
00195 
00196             for (; a.is_valid() && b.is_valid(); ++a, ++b)
00197             {
00198                 if (!(*a == *b))
00199                     return false;
00200             }
00201 
00202             if (a.is_valid() || b.is_valid())
00203                 return false;
00204 
00205             return true;
00206         } 
00207 
00208 
00209         template <typename T> 
00210         gsgl::index_t list<T>::size() const
00211         {
00212             return count;
00213         } 
00214         
00215 
00216         template <typename T> 
00217         void list<T>::clear()
00218         {
00219             list_node *prev, *cur = head;
00220 
00221             while (cur)
00222             {
00223                 prev = cur;
00224                 cur = cur->next;
00225                 delete prev;
00226             }
00227 
00228             head = 0;
00229             tail = 0;
00230             count = 0;
00231         } 
00232         
00233 
00234         template <typename T>
00235         bool list<T>::contains_index(const gsgl::index_t & index) const
00236         {
00237             return index < count;
00238         } 
00239 
00240 
00241         template <typename T> 
00242         const T & list<T>::item(const gsgl::index_t & index) const
00243         {
00244             list_node *cur = head;
00245             for (gsgl::index_t i = 0; cur && i < index; ++i)
00246                 cur = cur->next;
00247             
00248             if (cur)
00249                 return cur->item;
00250             else
00251                 throw memory_exception(__FILE__, __LINE__, L"List index out of bounds in list item reference.");
00252         } 
00253 
00254         
00255         template <typename T> 
00256         T & list<T>::item(const gsgl::index_t & index)
00257         {
00258             list_node *cur = head;
00259             for (gsgl::index_t i = 0; cur && i < index; ++i)
00260                 cur = cur->next;
00261             
00262             if (cur)
00263                 return cur->item;
00264             else
00265                 throw memory_exception(__FILE__, __LINE__, L"List index out of bounds in list item reference.");
00266         } 
00267 
00268 
00269         template <typename T> 
00270         void list<T>::append(const T & data)
00271         {
00272             if (tail)
00273             {
00274                 tail->next = new list_node(data, tail, 0);
00275                 tail = tail->next;
00276             }
00277             else
00278             {
00279                 head = tail = new list_node(data);
00280             }
00281             
00282             ++count;
00283         } 
00284 
00285 
00286 
00287         template <typename T>
00288         void list<T>::insert(const iterator & i, const T & item)
00289         {
00290             if (i.cur)
00291             {
00292                 list_node *new_node = new list_node(item, i.cur->prev, i.cur);
00293                 if (i.cur == head)
00294                     head = new_node;
00295                 if (i.cur->prev)
00296                     i.cur->prev->next = new_node;
00297                 i.cur->prev = new_node;
00298 
00299                 ++count;
00300             }
00301             else
00302             {
00303                 append(item);
00304             }
00305         } 
00306 
00307 
00308         template <typename T>
00309         void list<T>::remove(const iterator & i)
00310         {
00311             if (i.cur)
00312             {
00313                 if (i.cur == head)
00314                     head = i.cur->next;
00315                 if (i.cur == tail)
00316                     tail = i.cur->prev;
00317 
00318                 if (i.cur->prev)
00319                     i.cur->prev->next = i.cur->next;
00320                 if (i.cur->next)
00321                     i.cur->next->prev = i.cur->prev;
00322                 
00323                 i.cur->prev = 0;
00324                 i.cur->next = 0;
00325 
00326                 delete i.cur;
00327                 const_cast<list_node *>(i.cur) = 0;
00328 
00329                 --count;
00330             }
00331         } 
00332 
00333 
00334 
00335 
00336         template <typename T>
00337         class list_iterator
00338         {
00339             friend class list<T>;
00340             typename list<T>::list_node *cur;
00341 
00342         protected:
00343             list_iterator(const iterable<T, list_iterator<T> > & parent_iterable)
00344                 : cur(const_cast<list<T>::list_node *>( dynamic_cast<const list<T> &>(parent_iterable).head )) {}
00345             
00346             list_iterator(const list_iterator<T> & li)
00347                 : cur(li.cur) {}
00348 
00349             list_iterator & operator= (const list_iterator<T> & li)
00350             {
00351                 cur = li.cur;
00352                 return *this;
00353             }
00354 
00355 
00356             inline bool is_valid() const { return cur != 0; }
00357 
00358             inline const T & operator*() const
00359             {
00360                 if (cur)
00361                     return cur->item;
00362                 else
00363                     throw memory_exception(__FILE__, __LINE__, L"Iterator overflow in list iterator dereference.");
00364             }
00365 
00366             inline list_iterator & operator++()
00367             {
00368                 if (cur)
00369                     cur = cur->next;
00370                 else
00371                     throw memory_exception(__FILE__, __LINE__, L"Iterator overflow in list iterator preincrement.");
00372                 return *this;
00373             }
00374         }; 
00375 
00376         
00377     } 
00378     
00379 } 
00380 
00381 #endif