#ifndef __TREE_BASENODE_HPP__ #define __TREE_BASENODE_HPP__ /** * @file * @brief header file for the libtree++ library * @author Dominik Meyer * @date 2019-03-03 * @copyright 2019 GPLv2 by Dominik Meyer */ /* Copyright (C) 2019 Dominik Meyer This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include /** * @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 { private: /// the parent node of a node ;) std::shared_ptr parent; /// all child nodes of a node std::list> children; virtual std::shared_ptr 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 getRoot() const { if (parent==nullptr) { return std::const_pointer_cast(shared_from_this()); } return parent->getRoot(); } /** * @brief method to deep clone this node * * @return pointer to the cloned object */ std::shared_ptr clone() const { std::shared_ptr node = clone_(); node->clear(); std::list>::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 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 &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>::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>::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>::const_iterator getChildIterator(const std::shared_ptr 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 &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 &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 &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 &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 * @param end - iterator to the end of the container of objects of type std::shared_ptr */ template 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 * @param end - iterator to the end of the container of objects of type std::shared_ptr */ template 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 &c, std::list>::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 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 */ template void findAll(const std::string &t, Container &c) const { std::list>::const_iterator it; if (type() == t) { c.push_back(std::const_pointer_cast(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 */ template void findAllBase(const std::string &b, Container &c) const { std::list>::const_iterator it; if (base() == b) { c.push_back(std::const_pointer_cast(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 &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 &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 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 clone_() const {return std::make_shared();}; 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 clone_() const {return std::make_shared();}; 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