/* * Singly-linked list. * Copyright (C) 2014 Pavel Kirienko */ #ifndef UAVCAN_UTIL_LINKED_LIST_HPP_INCLUDED #define UAVCAN_UTIL_LINKED_LIST_HPP_INCLUDED #include #include #include namespace uavcan { /** * Classes that are supposed to be linked-listed should derive this. */ template 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 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 void insertBefore(T* node, Predicate predicate); /** * Removes only the first occurence of the node. * Complexity: O(N) */ void remove(const T* node); }; // ---------------------------------------------------------------------------- /* * LinkedListRoot<> */ template unsigned LinkedListRoot::getLength() const { T* node = root_; unsigned cnt = 0; while (node) { cnt++; node = node->getNextListNode(); } return cnt; } template void LinkedListRoot::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 template void LinkedListRoot::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 void LinkedListRoot::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