3 * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
10 * As a special exception, you may use this file as part of a free software
11 * library without restriction. Specifically, if other files instantiate
12 * templates or use macros or inline functions from this file, or you compile
13 * this file and link it with other files to produce an executable, this
14 * file does not by itself cause the resulting executable to be covered by
15 * the GNU General Public License. This exception does not however
16 * invalidate any other reasons why the executable file might be covered by
17 * the GNU General Public License.
22 #include <l4/cxx/type_traits>
23 #include <l4/cxx/std_alloc>
24 #include <l4/cxx/std_ops>
28 * Classes: List_item, List<D, Alloc>
33 * \brief Basic list item.
35 * Basic item that can be member of a doubly linked, cyclic list.
41 * \brief Iterator for a list of ListItem-s.
43 * The Iterator iterates till it finds the first element again.
48 Iter(List_item *c, List_item *f) throw() : _c(c), _f(f) {}
49 Iter(List_item *f = 0) throw() : _c(f), _f(f) {}
51 List_item *operator * () const throw() { return _c; }
52 List_item *operator -> () const throw() { return _c; }
53 Iter &operator ++ () throw()
58 _c = _c->get_next_item();
66 Iter operator ++ (int) throw()
67 { Iter o = *this; operator ++ (); return o; }
69 Iter &operator -- () throw()
74 _c = _c->get_prev_item();
82 Iter operator -- (int) throw()
83 { Iter o = *this; operator -- (); return o; }
85 /** Remove item pointed to by iterator, and return pointer to element. */
86 List_item *remove_me() throw()
106 * \brief Iterator for derived classes from ListItem.
108 * Allows direct access to derived classes by * operator.
111 * class Foo : public ListItem
114 * typedef T_iter<Foo> Iter;
118 template< typename T, bool Poly = false>
119 class T_iter : public Iter
122 static bool const P = !Conversion<const T*, const List_item *>::exists
125 static List_item *cast_to_li(T *i, Int_to_type<true>) throw()
126 { return dynamic_cast<List_item*>(i); }
128 static List_item *cast_to_li(T *i, Int_to_type<false>) throw()
131 static T *cast_to_type(List_item *i, Int_to_type<true>) throw()
132 { return dynamic_cast<T*>(i); }
134 static T *cast_to_type(List_item *i, Int_to_type<false>) throw()
135 { return static_cast<T*>(i); }
139 template< typename O >
140 explicit T_iter(T_iter<O> const &o) throw()
141 : Iter(o) { dynamic_cast<T*>(*o); }
143 //TIter(CListItem *f) : Iter(f) {}
144 T_iter(T *f = 0) throw() : Iter(cast_to_li(f, Int_to_type<P>())) {}
145 T_iter(T *c, T *f) throw()
146 : Iter(cast_to_li(c, Int_to_type<P>()),
147 cast_to_li(f, Int_to_type<P>()))
150 inline T *operator * () const throw()
151 { return cast_to_type(Iter::operator * (),Int_to_type<P>()); }
152 inline T *operator -> () const throw()
153 { return operator * (); }
155 T_iter<T, Poly> operator ++ (int) throw()
156 { T_iter<T, Poly> o = *this; Iter::operator ++ (); return o; }
157 T_iter<T, Poly> operator -- (int) throw()
158 { T_iter<T, Poly> o = *this; Iter::operator -- (); return o; }
159 T_iter<T, Poly> &operator ++ () throw()
160 { Iter::operator ++ (); return *this; }
161 T_iter<T, Poly> &operator -- () throw()
162 { Iter::operator -- (); return *this; }
163 inline T *remove_me() throw();
166 List_item() throw() : _n(this), _p(this) {}
169 List_item(List_item const &) throw() : _n(this), _p(this) {}
172 /** Get previous item. */
173 List_item *get_prev_item() const throw() { return _p; }
175 /** Get next item. */
176 List_item *get_next_item() const throw() { return _n; }
178 /** Insert item p before this item. */
179 void insert_prev_item(List_item *p) throw()
182 List_item *pr = p->_p;
188 /** Insert item p after this item. */
189 void insert_next_item(List_item *p) throw()
197 /** Remove this item from the list. */
198 void remove_me() throw()
209 * \brief Append item to a list.
211 * Convenience function for empty-head corner case.
212 * \param h pointer to the current list head.
213 * \param p pointer to new item.
214 * \return the pointer to the new head.
216 template< typename C, typename N >
217 static inline C *push_back(C *head, N *p) throw();
220 * \brief Prepend item to a list.
222 * Convenience function for empty-head corner case.
223 * \param head pointer to the current list head.
224 * \param p pointer to new item.
225 * \return the pointer to the new head.
227 template< typename C, typename N >
228 static inline C *push_front(C *head, N *p) throw();
231 * \brief Remove item from a list.
233 * Convenience function for remove-head corner case.
234 * \param head pointer to the current list head.
235 * \param p pointer to the item to remove.
236 * \return the pointer to the new head.
238 template< typename C, typename N >
239 static inline C *remove(C *head, N *p) throw();
246 /* IMPLEMENTATION -----------------------------------------------------------*/
247 template< typename C, typename N >
248 C *List_item::push_back(C *h, N *p) throw()
254 h->insert_prev_item(p);
258 template< typename C, typename N >
259 C *List_item::push_front(C *h, N *p) throw()
264 h->insert_prev_item(p);
268 template< typename C, typename N >
269 C *List_item::remove(C *h, N *p) throw()
280 h = static_cast<C*>(p->_n);
287 template< typename T, bool Poly >
289 T *List_item::T_iter<T, Poly>::remove_me() throw()
290 { return cast_to_type(Iter::remove_me(), Int_to_type<P>()); }
293 template< typename T >
294 class T_list_item : public List_item
297 T *next() const { return static_cast<T*>(List_item::get_next_item()); }
298 T *prev() const { return static_cast<T*>(List_item::get_prev_item()); }
302 template< typename LI >
312 void push_front(LI *e) { _h = LI::push_front(_h, e); }
313 void push_back(LI *e) { _h = LI::push_back(_h, e); }
314 void insert_before(LI *e, LI *p)
316 p->insert_prev_item(e);
320 void insert_after(LI *e, LI *p) { p->insert_next_item(e); }
323 { _h = LI::remove(_h, e); }
325 LI *head() const { return _h; }
329 * Doubly linked list, with internal allocation.
330 * Container for items of type D, implemented by a doubly linked list.
331 * Alloc defines the allocator policy.
333 template< typename D, template<typename A> class Alloc = New_allocator >
337 class E : public List_item
340 E(D const &d) throw() : data(d) {}
345 class Node : private E
348 typedef Alloc<Node> Node_alloc;
352 * Forward and backward iteratable.
357 List_item::T_iter<E> _i;
360 Iter(E *e) throw() : _i(e) {}
362 D &operator * () const throw() { return (*_i)->data; }
363 D &operator -> () const throw() { return (*_i)->data; }
365 Iter operator ++ (int) throw()
366 { Iter o = *this; operator ++ (); return o; }
367 Iter operator -- (int) throw()
368 { Iter o = *this; operator -- (); return o; }
369 Iter &operator ++ () throw() { ++_i; return *this; }
370 Iter &operator -- () throw() { --_i; return *this; }
372 /** operator for testing validity (syntactically equal to pointers) */
373 operator E* () const throw() { return *_i; }
376 List(Alloc<Node> const &a = Alloc<Node>()) throw() : _h(0), _l(0), _a(a) {}
378 /** Add element at the end of the list. */
379 void push_back(D const &d) throw()
381 void *n = _a.alloc();
383 _h = E::push_back(_h, new (n) E(d));
387 /** Add element at the beginning of the list. */
388 void push_front(D const &d) throw()
390 void *n = _a.alloc();
392 _h = E::push_front(_h, new (n) E(d));
396 /** Remove element pointed to by the iterator. */
397 void remove(Iter const &i) throw()
398 { E *e = i; _h = E::remove(_h, e); --_l; _a.free(e); }
400 /** Get the length of the list. */
401 unsigned long size() const throw() { return _l; }
403 /** Random access. Complexity is O(n). */
404 D const &operator [] (unsigned long idx) const throw()
405 { Iter i = _h; for (; idx && *i; ++i, --idx) ; return *i; }
407 /** Random access. Complexity is O(n). */
408 D &operator [] (unsigned long idx) throw()
409 { Iter i = _h; for (; idx && *i; ++i, --idx) ; return *i; }
411 /** Get iterator for the list elements. */
412 Iter items() throw() { return Iter(_h); }