/**
 * @file      lib.LinkedNode.hpp
 * @author    Sergey Baigudin, sergey@baigudin.software
 * @copyright 2016-2022, Sergey Baigudin, Baigudin Software
 */
#ifndef LIB_LINKEDNODE_HPP_
#define LIB_LINKEDNODE_HPP_

#include "lib.NonCopyable.hpp"

namespace eoos
{
namespace lib
{

/**
 * @class LinkedNode<T,A>
 * @brief Element for linked lists.
 *
 * @tparam T Data type of element.
 * @tparam A Heap memory allocator class.
 */
template <typename T, class A = Allocator>
class LinkedNode : public NonCopyable<A>
{
    typedef NonCopyable<A> Parent;

public:

    /**
     * @brief Constructor.
     *
     * @note A passed element will be copied to the internal data
     * structure by calling a copy constructor so that the element
     * might be invalidated after the function called.
     *
     * @param element An user element of this node.
     */
    LinkedNode(T const& element) 
        : NonCopyable<A>()
        , prev_(this)
        , next_(this)
        , index_(0)
        , element_(element) {
    }

    /**
     * @brief Destructor.
     */
    virtual ~LinkedNode()
    {
        LinkedNode* node( this->next_ );
        while(node->index_ != 0)
        {
            node->index_--; ///< SCA MISRA-C++:2008 Defected Rule 5-2-10
            node = node->next_;
        }
        next_->prev_ = prev_;
        prev_->next_ = next_;
        prev_ = this;
        next_ = this;
    }

    /**
     * @brief Inserts a new element after this.
     *
     * Function links a node after this and reindexes
     * chain of nodes starts from given node.
     *
     * @param node Pointer to inserted node.
     */
    void insertAfter(LinkedNode<T,A>* node)
    {
        link(node);
        node->index_ = index_;
        do
        {
            node->index_++; ///< SCA MISRA-C++:2008 Defected Rule 5-2-10
            node = node->next_;
        }
        while(node->index_ != 0);
    }

    /**
     * @brief Inserts a new element before this.
     *
     * Function links a node before this and reindexes
     * chain of nodes starts from this node.
     *
     * @param node Pointer to inserted node.
     */
    void insertBefore(LinkedNode<T,A>* node)
    {
        prev_->link(node);
        node->index_ = index_;
        node = this;
        do
        {
            node->index_++; ///< SCA MISRA-C++:2008 Defected Rule 5-2-10
            node = node->next_;
        }
        while(node->index_ != 0);
    }

    /**
     * @brief Returns previous element.
     *
     * @return Previous element.
     */
    LinkedNode<T,A>* getPrevious() ///< SCA MISRA-C++:2008 Justified Rule 9-3-3
    {
        return prev_;
    }

    /**
     * @brief Returns previous element.
     *
     * @return Previous element.
     */
    LinkedNode<T,A> const* getPrevious() const
    {
        return prev_;
    }

    /**
     * @brief Returns next element.
     *
     * @return The next element.
     */
    LinkedNode<T,A>* getNext() ///< SCA MISRA-C++:2008 Justified Rule 9-3-3
    {
        return next_;
    }

    /**
     * @brief Returns next element.
     *
     * @return The next element.
     */
    LinkedNode<T,A> const* getNext() const
    {
        return next_;
    }

    /**
     * @brief Returns the element.
     *
     * @return The next element.
     */
    T& getElement()
    {
        return element_; ///< SCA MISRA-C++:2008 Justified Rule 9-3-2
    }

    /**
     * @brief Returns the element.
     *
     * @return The next element.
     */
    T const& getElement() const
    {
        return element_;
    }

    /**
     * @brief Returns the element index.
     *
     * @return An element index.
     */
    int32_t getIndex() const
    {
        return index_;
    }

private:

    /**
     * @brief Links a given node after this.
     *
     * @param node Pointer to linking node.
     */
    void link(LinkedNode<T,A>* node)
    {
        next_->prev_ = node;
        node->next_ = next_;
        next_ = node;
        node->prev_ = this;
    }   

    /**
     * @brief Previous node.
     */
    LinkedNode* prev_;

    /**
     * @brief Next node.
     */
    LinkedNode* next_;

    /**
     * @brief Index of the node.
     */
    int32_t index_;

    /**
     * @brief Containing element.
     */
    T element_;

};

} // namespace lib
} // namespace eoos
#endif // LIB_LINKEDNODE_HPP_

Generated by OpenCppCoverage (Version: 0.9.9.0)