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