forked from Research/WhisperCom
454 lines
13 KiB
C++
454 lines
13 KiB
C++
|
#ifndef __TREE_BASENODE_HPP__
|
||
|
#define __TREE_BASENODE_HPP__
|
||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||
|
*/
|
||
|
/**
|
||
|
* @file
|
||
|
* @brief header file for the libtree++ library
|
||
|
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||
|
* @date 2019-03-03
|
||
|
* @copyright 2021 MPLv2 by Dominik Meyer
|
||
|
*/
|
||
|
#include <memory>
|
||
|
#include <string>
|
||
|
#include <list>
|
||
|
#include <algorithm>
|
||
|
#include <iostream>
|
||
|
|
||
|
/**
|
||
|
* @brief main namespace for the libtree++ library
|
||
|
*/
|
||
|
namespace Tree
|
||
|
{
|
||
|
/**
|
||
|
* @brief base node for all nodes within the tree, implementing base tree methods
|
||
|
*/
|
||
|
class BaseNode : public std::enable_shared_from_this<Tree::BaseNode>
|
||
|
{
|
||
|
private:
|
||
|
/// the parent node of a node ;)
|
||
|
std::shared_ptr<Tree::BaseNode> parent;
|
||
|
|
||
|
/// all child nodes of a node
|
||
|
std::list<std::shared_ptr<Tree::BaseNode>> children;
|
||
|
|
||
|
|
||
|
virtual std::shared_ptr<Tree::BaseNode> clone_() const = 0;
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* @brief clear the node of parent and children, but do not delete the children, required for cloning
|
||
|
*
|
||
|
*/
|
||
|
void clear() {
|
||
|
children.clear();
|
||
|
parent=nullptr;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @brief get the root of the tree
|
||
|
*
|
||
|
*/
|
||
|
std::shared_ptr<Tree::BaseNode> getRoot() const
|
||
|
{
|
||
|
if (parent==nullptr)
|
||
|
{
|
||
|
return std::const_pointer_cast<Tree::BaseNode>(shared_from_this());
|
||
|
}
|
||
|
|
||
|
return parent->getRoot();
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief method to deep clone this node
|
||
|
*
|
||
|
* @return pointer to the cloned object
|
||
|
*/
|
||
|
std::shared_ptr<Tree::BaseNode> clone() const
|
||
|
{
|
||
|
std::shared_ptr<Tree::BaseNode> node = clone_();
|
||
|
node->clear();
|
||
|
|
||
|
std::list<std::shared_ptr<Tree::BaseNode>>::const_iterator it;
|
||
|
for(it = children.begin(); it != children.end(); ++it)
|
||
|
{
|
||
|
node->addChild((*it)->clone());
|
||
|
}
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief print the tree starting with the current node to stdout
|
||
|
*
|
||
|
* @param depth - used for indenting the tree
|
||
|
*/
|
||
|
void printTree(const uint32_t depth);
|
||
|
|
||
|
/**
|
||
|
* @brief print the tree starting with the current node to stdout
|
||
|
*
|
||
|
* just calls printTree(0)
|
||
|
*/
|
||
|
void printTree() { printTree(0); }
|
||
|
|
||
|
/**
|
||
|
* @brief returns a string representing this node
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* @return std::string representing this node
|
||
|
*/
|
||
|
virtual const std::string toString() const = 0;
|
||
|
|
||
|
/**
|
||
|
* @brief returns the type of this node as a string
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* @return std::string representing the type of this node
|
||
|
*/
|
||
|
virtual const std::string type() const = 0;
|
||
|
|
||
|
/**
|
||
|
* @brief returns the base of this node as a string
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* a base is some kind of way to group nodes belonging to a certain topic
|
||
|
*
|
||
|
* @return std::string representing the type of this node
|
||
|
*/
|
||
|
virtual const std::string base() const = 0;
|
||
|
|
||
|
/**
|
||
|
* @brief return the parent node of the node
|
||
|
*
|
||
|
* @return nullptr - no parent is set, therefore, it should be a root node
|
||
|
* @return a std::shared_ptr to the the parent node
|
||
|
*/
|
||
|
const std::shared_ptr<Tree::BaseNode> getParent() const { return parent;}
|
||
|
|
||
|
/**
|
||
|
* @brief set the parent node of this node
|
||
|
*
|
||
|
* @param p - the parent node as a shared_ptr
|
||
|
*/
|
||
|
void setParent(const std::shared_ptr<Tree::BaseNode> &p) {parent=p;}
|
||
|
|
||
|
/**
|
||
|
* @brief returns an iterator to the beginning of the list of children
|
||
|
*
|
||
|
* @return iterator to the beginning of the list of children
|
||
|
*/
|
||
|
std::list<std::shared_ptr<Tree::BaseNode>>::const_iterator getChildrenBegin() const {return children.begin();}
|
||
|
|
||
|
/**
|
||
|
* @brief returns an iterator to the end of the list of children
|
||
|
*
|
||
|
* @return iterator to the end of the list of children
|
||
|
*/
|
||
|
std::list<std::shared_ptr<Tree::BaseNode>>::const_iterator getChildrenEnd() const {return children.end();}
|
||
|
|
||
|
/**
|
||
|
* @brief returns the nr of direct children
|
||
|
*
|
||
|
* @return the nr of direct children
|
||
|
*/
|
||
|
const unsigned int getNrDirectChildren() const { return children.size(); }
|
||
|
|
||
|
/**
|
||
|
* @brief returns the nr of all children
|
||
|
*
|
||
|
* @return the nr of all children
|
||
|
*/
|
||
|
const unsigned int getNrChildren() const;
|
||
|
|
||
|
/**
|
||
|
* @brief get the iterator of the given child
|
||
|
*
|
||
|
* @param child - the childnode to find the iterator for
|
||
|
* @return - the const iterator for the given child
|
||
|
*/
|
||
|
std::list<std::shared_ptr<Tree::BaseNode>>::const_iterator getChildIterator(const std::shared_ptr<const Tree::BaseNode> child) const;
|
||
|
|
||
|
/**
|
||
|
* @brief deletes all the children and their children and ... from the tree
|
||
|
*/
|
||
|
void deleteChildren();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief deletes the given node and all its children
|
||
|
*
|
||
|
* @param c - the node to delete
|
||
|
*
|
||
|
*/
|
||
|
void deleteChild(const std::shared_ptr<Tree::BaseNode> &c);
|
||
|
|
||
|
/**
|
||
|
* @brief remove the given node from the children of the node
|
||
|
*
|
||
|
* remove is not delete. The node gets just disconnected from the tree
|
||
|
*
|
||
|
* @param c - the node to remove from the nodes list of children
|
||
|
*
|
||
|
*/
|
||
|
void removeChild(const std::shared_ptr<const Tree::BaseNode> &c);
|
||
|
|
||
|
/**
|
||
|
* @brief adds a child to the node which is already a shared_ptr
|
||
|
*
|
||
|
* @param c - a shared_ptr to a BaseNode
|
||
|
*/
|
||
|
void addChild(const std::shared_ptr<Tree::BaseNode> &c) {
|
||
|
if (c!=nullptr)
|
||
|
{
|
||
|
c->setParent(shared_from_this());
|
||
|
children.push_back(c);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief prepends a child to the node which is already a shared_ptr
|
||
|
*
|
||
|
* @param c - a shared_ptr to a BaseNode
|
||
|
*/
|
||
|
void prependChild(const std::shared_ptr<Tree::BaseNode> &c) {c->setParent(shared_from_this()); children.push_front(c); }
|
||
|
|
||
|
/**
|
||
|
* @brief adds a container of nodes to the list of children
|
||
|
*
|
||
|
* @param begin - iterator to the beginning of the container of objects of type std::shared_ptr<Tree::BaseNode>
|
||
|
* @param end - iterator to the end of the container of objects of type std::shared_ptr<Tree::BaseNode>
|
||
|
*/
|
||
|
template <typename Iter>
|
||
|
void addChildren(Iter begin, Iter end) { std::copy( begin, end, std::back_inserter( children ) );}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief prepends a container of nodes to the list of children
|
||
|
*
|
||
|
* @param begin - iterator to the beginning of the container of objects of type std::shared_ptr<Tree::BaseNode>
|
||
|
* @param end - iterator to the end of the container of objects of type std::shared_ptr<Tree::BaseNode>
|
||
|
*/
|
||
|
template <typename Iter>
|
||
|
void prependChildren(Iter begin, Iter end) { std::copy( begin, end, std::front_inserter( children ) );}
|
||
|
|
||
|
/**
|
||
|
* @brief inserts a child before the given iterator which is already a shared_ptr
|
||
|
*
|
||
|
* @param c - a shared_ptr to a BaseNode
|
||
|
* @param it - the iterator before which to insert the node
|
||
|
*/
|
||
|
void insertChild(const std::shared_ptr<Tree::BaseNode> &c, std::list<std::shared_ptr<Tree::BaseNode>>::const_iterator it) {c->setParent(shared_from_this());children.insert(it,c);}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief finds the next node in the tree of a given type
|
||
|
*
|
||
|
* @param t - the type of the node as a string
|
||
|
*
|
||
|
* @return nullptr - a node of that type could not be found
|
||
|
* @return the found node as a shared_ptr
|
||
|
*/
|
||
|
std::shared_ptr<const Tree::BaseNode> findNext(const std::string &t) const;
|
||
|
|
||
|
/**
|
||
|
* @brief finds all nodes of a given type
|
||
|
*
|
||
|
* @param t - the type of the node as a string
|
||
|
* @param c - a container for holding all found nodes, has to be holding objects of type std::shared_ptr<Tree::BaseNode>
|
||
|
*/
|
||
|
template <typename Container>
|
||
|
void findAll(const std::string &t, Container &c) const
|
||
|
{
|
||
|
std::list<std::shared_ptr<Tree::BaseNode>>::const_iterator it;
|
||
|
if (type() == t)
|
||
|
{
|
||
|
c.push_back(std::const_pointer_cast<Tree::BaseNode>(shared_from_this()));
|
||
|
}
|
||
|
|
||
|
for(it = children.begin(); it != children.end(); ++it)
|
||
|
{
|
||
|
(*it)->findAll(t,c);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief finds all nodes of a given base
|
||
|
*
|
||
|
* @param b - the base type of the node as a string
|
||
|
* @param c - a container for holding all found nodes, has to be holding objects of type std::shared_ptr<Tree::BaseNode>
|
||
|
*/
|
||
|
template <class Container>
|
||
|
void findAllBase(const std::string &b, Container &c) const
|
||
|
{
|
||
|
std::list<std::shared_ptr<Tree::BaseNode>>::const_iterator it;
|
||
|
|
||
|
if (base() == b)
|
||
|
{
|
||
|
c.push_back(std::const_pointer_cast<Tree::BaseNode>(shared_from_this()));
|
||
|
}
|
||
|
|
||
|
for(it = children.begin(); it != children.end(); ++it)
|
||
|
{
|
||
|
(*it)->findAllBase(b,c);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief checks if the given node is a direct child of this node
|
||
|
*
|
||
|
* @param n - shared_ptr of the node to check
|
||
|
*
|
||
|
* @return true - the node is a direct child
|
||
|
* @return false - the node is not a direct child
|
||
|
*/
|
||
|
const bool isDirectChild(std::shared_ptr<Tree::BaseNode> &n) const;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief checks if the given node is a child of this node
|
||
|
*
|
||
|
* @param n - shared_ptr of the node to check
|
||
|
*
|
||
|
* @return true - the node is a child
|
||
|
* @return false - the node is not a child
|
||
|
*/
|
||
|
const bool isChild(std::shared_ptr<Tree::BaseNode> &n) const;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief replaces this node within the tree with the given one
|
||
|
*
|
||
|
* this means moving all children to the given node and setting all of their parents
|
||
|
* to the new node
|
||
|
*
|
||
|
* @param n - the new node to replace the current one with
|
||
|
*/
|
||
|
void replace(std::shared_ptr<Tree::BaseNode> n);
|
||
|
|
||
|
/**
|
||
|
* @brief overriding the to string operator
|
||
|
*
|
||
|
* used to convert the object on the fly to a string
|
||
|
*
|
||
|
* @return a string representing this object
|
||
|
*/
|
||
|
operator std::string() const { return toString(); }
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @brief stream operator override
|
||
|
*
|
||
|
* make it possible to use nodes within output streams
|
||
|
*
|
||
|
* @param Str - the output stream to stream to ;)
|
||
|
* @param v - the node which should be streamed to Str
|
||
|
*
|
||
|
* @return the outstream returned
|
||
|
*/
|
||
|
|
||
|
inline std::ostream & operator<<(std::ostream & Str, const Tree::BaseNode &v) {
|
||
|
Str << v.toString();
|
||
|
return Str;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Some basic Node Types
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @brief class representing the Root of a Tree
|
||
|
*/
|
||
|
class TreeRoot : public Tree::BaseNode
|
||
|
{
|
||
|
private:
|
||
|
virtual std::shared_ptr<Tree::BaseNode> clone_() const {return std::make_shared<Tree::TreeRoot>();};
|
||
|
|
||
|
public:
|
||
|
/**
|
||
|
* @brief returns the type of this node as a string
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* @return std::string representing the type of this node
|
||
|
*/
|
||
|
const std::string type() const { return "Tree::TreeRoot";}
|
||
|
|
||
|
/**
|
||
|
* @brief returns the base of this node as a string
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* a base is some kind of way to group nodes belonging to a certain topic
|
||
|
*
|
||
|
* @return std::string representing the type of this node
|
||
|
*/
|
||
|
const std::string base() const { return "Tree::Base";}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief returns a string representing this node
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* @return std::string representing this node
|
||
|
*/
|
||
|
virtual const std::string toString() const { return type();};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @brief class representing a temporary node within the tree
|
||
|
*/
|
||
|
class TempNode : public Tree::BaseNode
|
||
|
{
|
||
|
private:
|
||
|
virtual std::shared_ptr<Tree::BaseNode> clone_() const {return std::make_shared<Tree::TempNode>();};
|
||
|
public:
|
||
|
/**
|
||
|
* @brief returns the type of this node as a string
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* @return std::string representing the type of this node
|
||
|
*/
|
||
|
const std::string type() const { return "Tree::TempNode";}
|
||
|
|
||
|
/**
|
||
|
* @brief returns the base of this node as a string
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* a base is some kind of way to group nodes belonging to a certain topic
|
||
|
*
|
||
|
* @return std::string representing the type of this node
|
||
|
*/
|
||
|
const std::string base() const { return "Tree::Base";}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief returns a string representing this node
|
||
|
*
|
||
|
* this method has to be implemented by all nodes extending this class
|
||
|
*
|
||
|
* @return std::string representing this node
|
||
|
*/
|
||
|
virtual const std::string toString() const { return type();};
|
||
|
};
|
||
|
|
||
|
}; // namespace Tree
|
||
|
|
||
|
|
||
|
#endif
|