mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-28 04:30:34 +08:00
176 lines
3.4 KiB
C++
176 lines
3.4 KiB
C++
/*
|
|
* Singly-linked list.
|
|
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
|
*/
|
|
|
|
#ifndef UAVCAN_UTIL_LINKED_LIST_HPP_INCLUDED
|
|
#define UAVCAN_UTIL_LINKED_LIST_HPP_INCLUDED
|
|
|
|
#include <cstdlib>
|
|
#include <cassert>
|
|
#include <uavcan/build_config.hpp>
|
|
|
|
namespace uavcan
|
|
{
|
|
/**
|
|
* Classes that are supposed to be linked-listed should derive this.
|
|
*/
|
|
template <typename T>
|
|
class UAVCAN_EXPORT LinkedListNode
|
|
{
|
|
T* next_;
|
|
|
|
protected:
|
|
LinkedListNode()
|
|
: next_(NULL)
|
|
{ }
|
|
|
|
~LinkedListNode() { }
|
|
|
|
public:
|
|
T* getNextListNode() const { return next_; }
|
|
|
|
void setNextListNode(T* node)
|
|
{
|
|
next_ = node;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Linked list root.
|
|
*/
|
|
template <typename T>
|
|
class UAVCAN_EXPORT LinkedListRoot
|
|
{
|
|
T* root_;
|
|
|
|
public:
|
|
LinkedListRoot()
|
|
: root_(NULL)
|
|
{ }
|
|
|
|
T* get() const { return root_; }
|
|
bool isEmpty() const { return get() == NULL; }
|
|
|
|
/**
|
|
* Complexity: O(N)
|
|
*/
|
|
unsigned getLength() const;
|
|
|
|
/**
|
|
* Inserts the node to the beginning of the list.
|
|
* If the node is already present in the list, it will be relocated to the beginning.
|
|
* Complexity: O(N)
|
|
*/
|
|
void insert(T* node);
|
|
|
|
/**
|
|
* Inserts the node immediately before the node X where predicate(X) returns true.
|
|
* If the node is already present in the list, it can be relocated to a new position.
|
|
* Complexity: O(2N) (calls remove())
|
|
*/
|
|
template <typename Predicate>
|
|
void insertBefore(T* node, Predicate predicate);
|
|
|
|
/**
|
|
* Removes only the first occurence of the node.
|
|
* Complexity: O(N)
|
|
*/
|
|
void remove(const T* node);
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/*
|
|
* LinkedListRoot<>
|
|
*/
|
|
template <typename T>
|
|
unsigned LinkedListRoot<T>::getLength() const
|
|
{
|
|
T* node = root_;
|
|
unsigned cnt = 0;
|
|
while (node)
|
|
{
|
|
cnt++;
|
|
node = node->getNextListNode();
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
template <typename T>
|
|
void LinkedListRoot<T>::insert(T* node)
|
|
{
|
|
if (node == NULL)
|
|
{
|
|
UAVCAN_ASSERT(0);
|
|
return;
|
|
}
|
|
remove(node); // Making sure there will be no loops
|
|
node->setNextListNode(root_);
|
|
root_ = node;
|
|
}
|
|
|
|
template <typename T>
|
|
template <typename Predicate>
|
|
void LinkedListRoot<T>::insertBefore(T* node, Predicate predicate)
|
|
{
|
|
if (node == NULL)
|
|
{
|
|
UAVCAN_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
remove(node);
|
|
|
|
if (root_ == NULL || predicate(root_))
|
|
{
|
|
node->setNextListNode(root_);
|
|
root_ = node;
|
|
}
|
|
else
|
|
{
|
|
T* p = root_;
|
|
while (p->getNextListNode())
|
|
{
|
|
if (predicate(p->getNextListNode()))
|
|
{
|
|
break;
|
|
}
|
|
p = p->getNextListNode();
|
|
}
|
|
node->setNextListNode(p->getNextListNode());
|
|
p->setNextListNode(node);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void LinkedListRoot<T>::remove(const T* node)
|
|
{
|
|
if (root_ == NULL || node == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (root_ == node)
|
|
{
|
|
root_ = root_->getNextListNode();
|
|
}
|
|
else
|
|
{
|
|
T* p = root_;
|
|
while (p->getNextListNode())
|
|
{
|
|
if (p->getNextListNode() == node)
|
|
{
|
|
p->setNextListNode(p->getNextListNode()->getNextListNode());
|
|
break;
|
|
}
|
|
p = p->getNextListNode();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif // UAVCAN_UTIL_LINKED_LIST_HPP_INCLUDED
|