TUM/2016/ppc/common/include/util/SLinkedListSet.h

442 lines
7.4 KiB
C
Raw Permalink Normal View History

2016-07-03 23:18:54 +02:00
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef SLINKEDLIST_H_
#define SLINKEDLIST_H_
#include "util/SBaseTypes.h"
#include "util/SIteratorBaseTypes.h"
#include "util/CompileTimeConstraints.h"
#include <cassert>
template<typename T>
class SLinkedListSetNode
{
public:
typedef T value_type;
SLinkedListSetNode() :
fpNext(0L),
fAddedToList(false)
{}
T* getNext() const
{
return fpNext;
}
void setNext(T* pNext)
{
fpNext = pNext;
}
void addToList()
{
assert(!fAddedToList);
fAddedToList = true;
}
void removeFromList()
{
fAddedToList = false;
}
private:
SLinkedListSetNode(const SLinkedListSetNode&);
SLinkedListSetNode& operator=(const SLinkedListSetNode&);
T* fpNext;
bool fAddedToList;
};
template<typename T>
class SLinkedListSetIterator;
template<typename T>
class SLinkedListSet
: common::Derived_from<T, SLinkedListSetNode<T> >
{
private:
/** type of list itsself */
typedef SLinkedListSet<T> self_type;
public:
/** type of values stored in vector */
typedef typename STypeTraits<T>::value_type value_type;
/** pointer to value */
typedef typename STypeTraits<T>::pointer pointer;
/** reference to value */
typedef typename STypeTraits<T>::reference reference;
/** const reference to value */
typedef typename STypeTraits<T>::const_reference const_reference;
/** unsigned integral type */
typedef typename STypeTraits<T>::size_type size_type;
/** signed integral type */
typedef typename STypeTraits<T>::difference_type difference_type;
/** iterator type */
typedef SLinkedListSetIterator<T> iterator;
/** const iterator type */
typedef SLinkedListSetIterator<const T> const_iterator;
SLinkedListSet() :
fpFirst(0L),
fpLast(0L)
{
clear();
}
/**
* @note
* O(n)!
* @todo
* Maybe a field would be better
*/
size_type size() const
{
size_type size = (fpFirst) ? 1 : 0;
for (const T* pNode = fpFirst; pNode != fpLast; pNode = pNode->getNext())
{
++size;
}
return size;
}
bool empty() const
{
return (fpFirst == 0L);
}
void clear()
{
while (!empty())
{
pop_front();
}
fpFirst = 0L;
fpLast = 0L;
}
const_reference front() const
{
assert(fpFirst);
return *fpFirst;
}
reference front()
{
return const_cast<reference>(
static_cast<const self_type&>(
*this).front());
}
const_reference back() const
{
assert(fpLast);
return *fpLast;
}
reference back()
{
return const_cast<reference>(
static_cast<const self_type&>(
*this).back());
}
void push_front(T& node)
{
if (contains_node(&node))
{
return;
}
node.addToList();
node.setNext(fpFirst);
fpFirst = &node;
if (!fpLast)
{//inserted first node
fpLast = fpFirst;
fpFirst->setNext(0L);
}
}
void push_back(T& node)
{
if (empty())
{//inserted first node
fpFirst = &node;
}
else
{
if (contains_node(&node))
{
return;
}
fpLast->setNext(&node);
}
node.addToList();
fpLast = &node;
fpLast->setNext(0L);
}
void pop_front()
{
if (!fpFirst)
{
return;
}
fpFirst->removeFromList();
fpFirst = fpFirst->getNext();
if (!fpFirst)
{//removed last element
fpLast = 0L;
}
}
void pop_back();
iterator begin()
{
return iterator(fpFirst);
}
const_iterator begin() const
{
return const_iterator(fpFirst);
}
iterator end()
{
return iterator(0L);
}
const_iterator end() const
{
return const_iterator(0L);
}
iterator erase(iterator pos);
iterator insert(iterator pos, T& value);
void remove(const T& value);
bool contains(const T& value) const
{
return contains_node(&value);
}
private:
SLinkedListSet(const SLinkedListSet&);
SLinkedListSet& operator=(const SLinkedListSet&);
T* findPredecessor(const T* pNode) const
{
T* pResult = fpFirst;
while ((pResult != 0L) && (pResult->getNext() != pNode))
{
pResult = pResult->getNext();
}
return pResult;
}
bool contains_node(const T* pNodeToFind) const;
T* fpFirst;
T* fpLast;
};
template<typename T>
bool SLinkedListSet<T>::contains_node(const T* pNodeToFind) const
{
T* pNode = fpFirst;
while (pNode != 0L)
{
if (pNodeToFind == pNode)
{
return true;
}
pNode = pNode->getNext();
}
return false;
}
template<typename T>
void SLinkedListSet<T>::pop_back()
{
if (!fpLast)
{
return;
}
fpLast->removeFromList();
if (fpFirst == fpLast)
{
clear();
}
else
{
fpLast = findPredecessor(fpLast);
assert(fpLast);
fpLast->setNext(0L);
}
}
template<typename T>
typename SLinkedListSet<T>::iterator SLinkedListSet<T>::erase(
SLinkedListSet<T>::iterator pos)
{
if (!fpFirst)
{
return end();
}
iterator next = pos;
++next;
if (pos == begin())
{//remove first element
pop_front();
}
else
{
pos->removeFromList();
T* pNode = findPredecessor(pos.operator->());
assert(pNode);
if (pNode->getNext() == fpLast)
{//removing last element
fpLast = pNode;
}
pNode->setNext(pos->getNext());
}
return next;
}
template<typename T>
typename SLinkedListSet<T>::iterator SLinkedListSet<T>::insert(
SLinkedListSet<T>::iterator pos,
T& value)
{
if (contains_node(&value))
{
return pos;
}
if (empty() || (pos == begin()))
{
push_front(value);
}
else if (pos == end())
{
push_back(value);
}
else
{
value.addToList();
T* pNode = findPredecessor(pos.operator->());
assert(pNode);
value.setNext(pNode->getNext());
pNode->setNext(&value);
}
return iterator(&value);
}
template<typename T>
void SLinkedListSet<T>::remove(const T& value)
{
if (&value == fpFirst)
{
pop_front();
}
else if (&value == fpLast)
{
pop_back();
}
else
{
const_cast<T&>(value).removeFromList();
T* pNode = findPredecessor(&value);
if (pNode)
{
pNode->setNext(value.getNext());
}
}
}
template <typename T>
bool operator==(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y);
template <typename T>
bool operator!=(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y);
template<typename T>
class SLinkedListSetIterator
{
public:
/** the iterators category */
typedef SForwardIteratorTag iterator_category;
/** value type of iterator */
typedef typename STypeTraits<T>::value_type value_type;
/** reference to value */
typedef typename STypeTraits<T>::reference reference;
/** pointer to value */
typedef typename STypeTraits<T>::pointer pointer;
/** signed integral type */
typedef typename STypeTraits<T>::difference_type difference_type;
SLinkedListSetIterator(T* pValue) :
fpValue(pValue)
{}
SLinkedListSetIterator(const SLinkedListSetIterator& rhs) :
fpValue(rhs.fpValue)
{}
SLinkedListSetIterator& operator=(const SLinkedListSetIterator& rhs)
{
fpValue = rhs.fpValue;
return *this;
}
SLinkedListSetIterator& operator++()
{
fpValue = fpValue->getNext();
return *this;
}
reference operator*()
{
return *fpValue;
}
pointer operator->()
{
return fpValue;
}
private:
friend bool operator==<T>(
const SLinkedListSetIterator<T>&,
const SLinkedListSetIterator<T>&);
friend bool operator!=<T>(
const SLinkedListSetIterator<T>&,
const SLinkedListSetIterator<T>&);
T* fpValue;
};
template<typename T>
inline bool operator==(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y)
{
return (x.fpValue == y.fpValue);
}
template<typename T>
inline bool operator!=(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y)
{
return !(x == y);
}
#endif /*SLINKEDLIST_H_*/