Files
moslab-code/src/l4/pkg/l4re-core/cxx/lib/tl/include/list
2025-09-12 15:55:45 +02:00

412 lines
9.1 KiB
C++

// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include <l4/cxx/type_traits>
#include <l4/cxx/std_alloc>
#include <l4/cxx/std_ops>
namespace cxx {
/*
* Classes: List_item, List<D, Alloc>
*/
/**
* \ingroup cxx_api
* \brief Basic list item.
*
* Basic item that can be member of a doubly linked, cyclic list.
*/
class List_item
{
public:
/**
* \brief Iterator for a list of ListItem-s.
*
* The Iterator iterates till it finds the first element again.
*/
class Iter
{
public:
Iter(List_item *c, List_item *f) noexcept : _c(c), _f(f) {}
Iter(List_item *f = 0) noexcept : _c(f), _f(f) {}
List_item *operator * () const noexcept { return _c; }
List_item *operator -> () const noexcept { return _c; }
Iter &operator ++ () noexcept
{
if (!_f)
_c = 0;
else
_c = _c->get_next_item();
if (_c == _f)
_c = 0;
return *this;
}
Iter operator ++ (int) noexcept
{ Iter o = *this; operator ++ (); return o; }
Iter &operator -- () noexcept
{
if (!_f)
_c = 0;
else
_c = _c->get_prev_item();
if (_c == _f)
_c = 0;
return *this;
}
Iter operator -- (int) noexcept
{ Iter o = *this; operator -- (); return o; }
/** Remove item pointed to by iterator, and return pointer to element. */
List_item *remove_me() noexcept
{
if (!_c)
return 0;
List_item *l = _c;
operator ++ ();
l->remove_me();
if (_f == l)
_f = _c;
return l;
}
private:
List_item *_c, *_f;
};
/**
* \brief Iterator for derived classes from ListItem.
*
* Allows direct access to derived classes by * operator.
*
* Example:
* class Foo : public ListItem
* {
* public:
* typedef T_iter<Foo> Iter;
* ...
* };
*/
template< typename T, bool Poly = false>
class T_iter : public Iter
{
private:
static bool const P = !Conversion<const T*, const List_item *>::exists
|| Poly;
static List_item *cast_to_li(T *i, Int_to_type<true>) noexcept
{ return dynamic_cast<List_item*>(i); }
static List_item *cast_to_li(T *i, Int_to_type<false>) noexcept
{ return i; }
static T *cast_to_type(List_item *i, Int_to_type<true>) noexcept
{ return dynamic_cast<T*>(i); }
static T *cast_to_type(List_item *i, Int_to_type<false>) noexcept
{ return static_cast<T*>(i); }
public:
template< typename O >
explicit T_iter(T_iter<O> const &o) noexcept
: Iter(o) { dynamic_cast<T*>(*o); }
//TIter(CListItem *f) : Iter(f) {}
T_iter(T *f = 0) noexcept : Iter(cast_to_li(f, Int_to_type<P>())) {}
T_iter(T *c, T *f) noexcept
: Iter(cast_to_li(c, Int_to_type<P>()),
cast_to_li(f, Int_to_type<P>()))
{}
inline T *operator * () const noexcept
{ return cast_to_type(Iter::operator * (),Int_to_type<P>()); }
inline T *operator -> () const noexcept
{ return operator * (); }
T_iter<T, Poly> operator ++ (int) noexcept
{ T_iter<T, Poly> o = *this; Iter::operator ++ (); return o; }
T_iter<T, Poly> operator -- (int) noexcept
{ T_iter<T, Poly> o = *this; Iter::operator -- (); return o; }
T_iter<T, Poly> &operator ++ () noexcept
{ Iter::operator ++ (); return *this; }
T_iter<T, Poly> &operator -- () noexcept
{ Iter::operator -- (); return *this; }
inline T *remove_me() noexcept;
};
List_item() noexcept : _n(this), _p(this) {}
protected:
List_item(List_item const &) noexcept : _n(this), _p(this) {}
public:
/** Get previous item. */
List_item *get_prev_item() const noexcept { return _p; }
/** Get next item. */
List_item *get_next_item() const noexcept { return _n; }
/** Insert item p before this item. */
void insert_prev_item(List_item *p) noexcept
{
p->_p->_n = this;
List_item *pr = p->_p;
p->_p = _p;
_p->_n = p;
_p = pr;
}
/** Insert item p after this item. */
void insert_next_item(List_item *p) noexcept
{
p->_p->_n = _n;
p->_p = this;
_n->_p = p;
_n = p;
}
/** Remove this item from the list. */
void remove_me() noexcept
{
if (_p != this)
{
_p->_n = _n;
_n->_p = _p;
}
_p = _n = this;
}
/**
* \brief Append item to a list.
*
* Convenience function for empty-head corner case.
* \param head Pointer to the current list head.
* \param p Pointer to new item.
* \return the pointer to the new head.
*/
template< typename C, typename N >
static inline C *push_back(C *head, N *p) noexcept;
/**
* \brief Prepend item to a list.
*
* Convenience function for empty-head corner case.
* \param head pointer to the current list head.
* \param p pointer to new item.
* \return the pointer to the new head.
*/
template< typename C, typename N >
static inline C *push_front(C *head, N *p) noexcept;
/**
* \brief Remove item from a list.
*
* Convenience function for remove-head corner case.
* \param head pointer to the current list head.
* \param p pointer to the item to remove.
* \return the pointer to the new head.
*/
template< typename C, typename N >
static inline C *remove(C *head, N *p) noexcept;
private:
List_item *_n, *_p;
};
/* IMPLEMENTATION -----------------------------------------------------------*/
template< typename C, typename N >
C *List_item::push_back(C *h, N *p) noexcept
{
if (!p)
return h;
if (!h)
return p;
h->insert_prev_item(p);
return h;
}
template< typename C, typename N >
C *List_item::push_front(C *h, N *p) noexcept
{
if (!p)
return h;
if (h)
h->insert_prev_item(p);
return p;
}
template< typename C, typename N >
C *List_item::remove(C *h, N *p) noexcept
{
if (!p)
return h;
if (!h)
return 0;
if (h == p)
{
if (p == p->_n)
h = 0;
else
h = static_cast<C*>(p->_n);
}
p->remove_me();
return h;
}
template< typename T, bool Poly >
inline
T *List_item::T_iter<T, Poly>::remove_me() noexcept
{ return cast_to_type(Iter::remove_me(), Int_to_type<P>()); }
template< typename T >
class T_list_item : public List_item
{
public:
T *next() const { return static_cast<T*>(List_item::get_next_item()); }
T *prev() const { return static_cast<T*>(List_item::get_prev_item()); }
};
template< typename LI >
class L_list
{
private:
LI *_h;
public:
L_list() : _h(0) {}
void push_front(LI *e) { _h = LI::push_front(_h, e); }
void push_back(LI *e) { _h = LI::push_back(_h, e); }
void insert_before(LI *e, LI *p)
{
p->insert_prev_item(e);
if (_h == p)
_h = e;
}
void insert_after(LI *e, LI *p) { p->insert_next_item(e); }
void remove(LI *e)
{ _h = LI::remove(_h, e); }
LI *head() const { return _h; }
};
/**
* Doubly linked list, with internal allocation.
* Container for items of type D, implemented by a doubly linked list.
* Alloc defines the allocator policy.
*/
template< typename D, template<typename A> class Alloc = New_allocator >
class List
{
private:
class E : public List_item
{
public:
E(D const &d) noexcept : data(d) {}
D data;
};
public:
class Node : private E
{};
typedef Alloc<Node> Node_alloc;
/**
* Iterator.
* Forward and backward iteratable.
*/
class Iter
{
private:
List_item::T_iter<E> _i;
public:
Iter(E *e) noexcept : _i(e) {}
D &operator * () const noexcept { return (*_i)->data; }
D &operator -> () const noexcept { return (*_i)->data; }
Iter operator ++ (int) noexcept
{ Iter o = *this; operator ++ (); return o; }
Iter operator -- (int) noexcept
{ Iter o = *this; operator -- (); return o; }
Iter &operator ++ () noexcept { ++_i; return *this; }
Iter &operator -- () noexcept { --_i; return *this; }
/** operator for testing validity (syntactically equal to pointers) */
operator E* () const noexcept { return *_i; }
};
List(Alloc<Node> const &a = Alloc<Node>()) noexcept : _h(0), _l(0), _a(a) {}
/** Add element at the end of the list. */
void push_back(D const &d) noexcept
{
void *n = _a.alloc();
if (!n) return;
_h = E::push_back(_h, new (n) E(d));
++_l;
}
/** Add element at the beginning of the list. */
void push_front(D const &d) noexcept
{
void *n = _a.alloc();
if (!n) return;
_h = E::push_front(_h, new (n) E(d));
++_l;
}
/** Remove element pointed to by the iterator. */
void remove(Iter const &i) noexcept
{ E *e = i; _h = E::remove(_h, e); --_l; _a.free(e); }
/** Get the length of the list. */
unsigned long size() const noexcept { return _l; }
/** Random access. Complexity is O(n). */
D const &operator [] (unsigned long idx) const noexcept
{ Iter i = _h; for (; idx && *i; ++i, --idx) { } return *i; }
/** Random access. Complexity is O(n). */
D &operator [] (unsigned long idx) noexcept
{ Iter i = _h; for (; idx && *i; ++i, --idx) { } return *i; }
/** Get iterator for the list elements. */
Iter items() noexcept { return Iter(_h); }
private:
E *_h;
unsigned _l;
Alloc<Node> _a;
};
};