440 lines
9.1 KiB
C++
440 lines
9.1 KiB
C++
// vi:set ft=cpp: -*- Mode: C++ -*-
|
|
/*
|
|
* (c) 2011 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
|
|
|
|
namespace cxx {
|
|
|
|
class D_list_item
|
|
{
|
|
public:
|
|
constexpr D_list_item() : _dli_next(nullptr), _dli_prev(nullptr) {}
|
|
|
|
D_list_item(D_list_item const &) = delete;
|
|
void operator = (D_list_item const &) = delete;
|
|
|
|
private:
|
|
friend struct D_list_item_policy;
|
|
|
|
D_list_item *_dli_next, *_dli_prev;
|
|
};
|
|
|
|
struct D_list_item_policy
|
|
{
|
|
typedef D_list_item Item;
|
|
static D_list_item *&prev(D_list_item *e) { return e->_dli_prev; }
|
|
static D_list_item *&next(D_list_item *e) { return e->_dli_next; }
|
|
static D_list_item *prev(D_list_item const *e) { return e->_dli_prev; }
|
|
static D_list_item *next(D_list_item const *e) { return e->_dli_next; }
|
|
};
|
|
|
|
template< typename T >
|
|
struct Sd_list_head_policy
|
|
{
|
|
typedef T *Head_type;
|
|
static T *head(Head_type h) { return h; }
|
|
static void set_head(Head_type &h, T *v) { h = v; }
|
|
};
|
|
|
|
template<
|
|
typename T,
|
|
typename C = D_list_item_policy
|
|
>
|
|
class D_list_cyclic
|
|
{
|
|
protected:
|
|
template< typename VALUE, typename ITEM >
|
|
class __Iterator
|
|
{
|
|
public:
|
|
typedef VALUE *Value_type;
|
|
typedef VALUE *value_type;
|
|
|
|
__Iterator() {}
|
|
|
|
bool operator == (__Iterator const &o) const
|
|
{ return _c == o._c; }
|
|
|
|
bool operator != (__Iterator const &o) const
|
|
{ return _c != o._c; }
|
|
|
|
__Iterator &operator ++ ()
|
|
{
|
|
_c = C::next(_c);
|
|
return *this;
|
|
}
|
|
|
|
__Iterator &operator -- ()
|
|
{
|
|
_c = C::prev(_c);
|
|
return *this;
|
|
}
|
|
|
|
Value_type operator * () const { return static_cast<Value_type>(_c); }
|
|
Value_type operator -> () const { return static_cast<Value_type>(_c); }
|
|
|
|
protected:
|
|
friend class D_list_cyclic;
|
|
|
|
explicit __Iterator(ITEM *s) : _c(s) {}
|
|
|
|
ITEM *_c;
|
|
};
|
|
|
|
public:
|
|
typedef T *Value_type;
|
|
typedef T *value_type;
|
|
typedef __Iterator<T, typename C::Item> Iterator;
|
|
typedef Iterator Const_iterator;
|
|
|
|
static void remove(T *e)
|
|
{
|
|
C::next(C::prev(e)) = C::next(e);
|
|
C::prev(C::next(e)) = C::prev(e);
|
|
C::next(e) = nullptr;
|
|
}
|
|
|
|
static Iterator erase(Iterator const &e)
|
|
{
|
|
typename C::Item *n = C::next(*e);
|
|
remove(*e);
|
|
return __iter(n);
|
|
}
|
|
|
|
static Iterator iter(T const *e) { return Iterator(const_cast<T*>(e)); }
|
|
|
|
static bool in_list(T const *e) { return C::next(const_cast<T*>(e)); }
|
|
static bool has_sibling(T const *e) { return C::next(const_cast<T*>(e)) != e; }
|
|
|
|
static Iterator insert_after(T *e, Iterator const &pos)
|
|
{
|
|
C::prev(e) = pos._c;
|
|
C::next(e) = C::next(pos._c);
|
|
C::prev(C::next(pos._c)) = e;
|
|
C::next(pos._c) = e;
|
|
return pos;
|
|
}
|
|
|
|
static Iterator insert_before(T *e, Iterator const &pos)
|
|
{
|
|
C::next(e) = pos._c;
|
|
C::prev(e) = C::prev(pos._c);
|
|
C::next(C::prev(pos._c)) = e;
|
|
C::prev(pos._c) = e;
|
|
return pos;
|
|
}
|
|
|
|
protected:
|
|
static void self_insert(typename C::Item *e)
|
|
{ C::next(e) = C::prev(e) = e; }
|
|
|
|
static void remove_last(T *e)
|
|
{ C::next(e) = nullptr; }
|
|
|
|
/**
|
|
* Splice the elements of `other_list` into the list before `pos`.
|
|
*
|
|
* \pre Must not be called for an empty `other_list`!
|
|
* \post Leaves the `other_list` in an invalid state.
|
|
*/
|
|
static void splice_heads(Const_iterator pos, typename C::Item *other_list)
|
|
{
|
|
typename C::Item *ins_next = pos._c;
|
|
typename C::Item *ins_prev = C::prev(pos._c);
|
|
typename C::Item *other_head = C::next(other_list);
|
|
typename C::Item *other_tail = C::prev(other_list);
|
|
|
|
C::next(ins_prev) = other_head;
|
|
C::prev(other_head) = ins_prev;
|
|
C::prev(ins_next) = other_tail;
|
|
C::next(other_tail) = ins_next;
|
|
}
|
|
|
|
static Iterator __iter(typename C::Item *e) { return Iterator(e); }
|
|
};
|
|
|
|
template<
|
|
typename T,
|
|
typename C = D_list_item_policy,
|
|
typename H = Sd_list_head_policy<T>,
|
|
bool BSS = false
|
|
>
|
|
class Sd_list : public D_list_cyclic<T, C>
|
|
{
|
|
private:
|
|
typedef D_list_cyclic<T, C> Base;
|
|
|
|
public:
|
|
class Iterator : public Base::Iterator
|
|
{
|
|
public:
|
|
Iterator &operator ++ ()
|
|
{
|
|
if (this->_c)
|
|
Base::Iterator::operator ++ ();
|
|
|
|
if (this->_c == _h)
|
|
this->_c = nullptr;
|
|
|
|
return *this;
|
|
}
|
|
|
|
Iterator &operator -- () = delete;
|
|
|
|
private:
|
|
friend class Sd_list;
|
|
|
|
explicit Iterator(T *h) : Base::Iterator(h), _h(h) {}
|
|
typename C::Item *_h;
|
|
};
|
|
|
|
class R_iterator : public Base::Iterator
|
|
{
|
|
public:
|
|
R_iterator &operator ++ ()
|
|
{
|
|
if (this->_c)
|
|
Base::Iterator::operator -- ();
|
|
|
|
if (this->_c == _h)
|
|
this->_c = nullptr;
|
|
|
|
return *this;
|
|
}
|
|
|
|
R_iterator &operator -- () = delete;
|
|
|
|
private:
|
|
friend class Sd_list;
|
|
|
|
explicit R_iterator(T *h) : Base::Iterator(h), _h(h) {}
|
|
typename C::Item *_h;
|
|
};
|
|
|
|
//typedef typename Base::Iterator Iterator;
|
|
enum Pos
|
|
{ Back, Front };
|
|
|
|
Sd_list()
|
|
{
|
|
if (!BSS)
|
|
H::set_head(_f, nullptr);
|
|
}
|
|
|
|
bool empty() const { return !H::head(_f); }
|
|
T *front() const { return H::head(_f); }
|
|
|
|
void remove(T *e)
|
|
{
|
|
T *h = H::head(_f);
|
|
if (e == C::next(e)) // must be the last
|
|
{
|
|
Base::remove_last(e);
|
|
H::set_head(_f, nullptr);
|
|
return;
|
|
}
|
|
|
|
if (e == H::head(_f))
|
|
H::set_head(_f, static_cast<T*>(C::next(h)));
|
|
|
|
Base::remove(e);
|
|
}
|
|
|
|
Iterator erase(Iterator const &e)
|
|
{
|
|
Iterator next = e;
|
|
++next;
|
|
|
|
remove(*e);
|
|
return next;
|
|
}
|
|
|
|
void push(T *e, Pos pos)
|
|
{
|
|
T *h = H::head(_f);
|
|
if (!h)
|
|
{
|
|
Base::self_insert(e);
|
|
H::set_head(_f, e);
|
|
}
|
|
else
|
|
{
|
|
Base::insert_before(e, this->iter(h));
|
|
if (pos == Front)
|
|
H::set_head(_f, e);
|
|
}
|
|
}
|
|
|
|
void push_back(T *e) { push(e, Back); }
|
|
void push_front(T *e) { push(e, Front); }
|
|
void rotate_to(T *h) { H::set_head(_f, h); }
|
|
|
|
typename H::Head_type const &head() const { return _f; }
|
|
typename H::Head_type &head() { return _f; }
|
|
|
|
Iterator begin() { return Iterator(H::head(_f)); }
|
|
Iterator end() { return Iterator(nullptr); }
|
|
|
|
R_iterator rbegin()
|
|
{
|
|
if (head())
|
|
return R_iterator(static_cast<T*>(C::prev(H::head(_f))));
|
|
return R_iterator(nullptr);
|
|
}
|
|
R_iterator rend() { return R_iterator(nullptr); }
|
|
|
|
private:
|
|
Sd_list(Sd_list const &);
|
|
void operator = (Sd_list const &);
|
|
|
|
typename H::Head_type _f;
|
|
};
|
|
|
|
template<
|
|
typename T,
|
|
typename C = D_list_item_policy,
|
|
bool BSS = false
|
|
>
|
|
class D_list : public D_list_cyclic<T, C>
|
|
{
|
|
private:
|
|
typedef D_list_cyclic<T, C> Base;
|
|
typedef typename C::Item Internal_type;
|
|
|
|
public:
|
|
enum Pos
|
|
{ Back, Front };
|
|
|
|
typedef typename Base::Iterator Iterator;
|
|
typedef typename Base::Const_iterator Const_iterator;
|
|
typedef T* value_type;
|
|
typedef T* Value_type;
|
|
|
|
D_list() { this->self_insert(&_h); }
|
|
~D_list() { clear(); }
|
|
|
|
D_list(D_list &&o)
|
|
{
|
|
if (o.empty())
|
|
{
|
|
this->self_insert(&_h);
|
|
}
|
|
else
|
|
{
|
|
Internal_type *p = C::prev(&o._h);
|
|
Internal_type *n = C::next(&o._h);
|
|
C::prev(&_h) = p;
|
|
C::next(&_h) = n;
|
|
C::next(p) = &_h;
|
|
C::prev(n) = &_h;
|
|
o.self_insert(&o._h);
|
|
}
|
|
}
|
|
|
|
D_list &operator=(D_list &&o)
|
|
{
|
|
if (&o == this)
|
|
return *this;
|
|
|
|
clear();
|
|
|
|
if (!o.empty())
|
|
{
|
|
Internal_type *p = C::prev(&o._h);
|
|
Internal_type *n = C::next(&o._h);
|
|
C::prev(&_h) = p;
|
|
C::next(&_h) = n;
|
|
C::next(p) = &_h;
|
|
C::prev(n) = &_h;
|
|
o.self_insert(&o._h);
|
|
}
|
|
}
|
|
|
|
D_list(D_list const &) = delete;
|
|
void operator = (D_list const &) = delete;
|
|
|
|
void splice(Const_iterator pos, D_list &&other)
|
|
{
|
|
if (other.empty())
|
|
return;
|
|
|
|
Base::splice_heads(pos, &other._h);
|
|
other.self_insert(&other._h);
|
|
}
|
|
|
|
bool empty() const { return C::next(&_h) == &_h; }
|
|
|
|
static void remove(T *e) { Base::remove(e); }
|
|
Iterator erase(Iterator const &e) { return Base::erase(e); }
|
|
|
|
void clear()
|
|
{
|
|
// Just clear the _dli_next pointers of all elements. It is the indicator
|
|
// that an element is not on a list.
|
|
Internal_type *i = C::next(&_h);
|
|
while (i != &_h)
|
|
{
|
|
Internal_type *d = i;
|
|
i = C::next(i);
|
|
C::next(d) = nullptr;
|
|
}
|
|
|
|
this->self_insert(&_h);
|
|
}
|
|
|
|
void push(T *e, Pos pos)
|
|
{
|
|
if (pos == Front)
|
|
Base::insert_after(e, end());
|
|
else
|
|
Base::insert_before(e, end());
|
|
}
|
|
|
|
void push_back(T *e) { push(e, Back); }
|
|
void push_front(T *e) { push(e, Front); }
|
|
|
|
/**
|
|
* Remove element from the end of the list and return it.
|
|
*
|
|
* \pre The list is not empty.
|
|
*/
|
|
T *pop_back()
|
|
{
|
|
T *ret = *(end()--);
|
|
remove(ret);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Remove element from the beginning of the list and return it.
|
|
*
|
|
* \pre The list is not empty.
|
|
*/
|
|
T *pop_front()
|
|
{
|
|
T *ret = *begin();
|
|
remove(ret);
|
|
return ret;
|
|
}
|
|
|
|
Iterator begin() const { return this->__iter(C::next(const_cast<Internal_type *>(&_h))); }
|
|
Iterator end() const { return this->__iter(const_cast<Internal_type *>(&_h)); }
|
|
|
|
bool has_sibling(T const *e)
|
|
{
|
|
return C::next(const_cast<T*>(e)) != &_h
|
|
|| C::prev(const_cast<T*>(e)) != &_h;
|
|
}
|
|
|
|
private:
|
|
Internal_type _h;
|
|
};
|
|
|
|
}
|
|
|