
4 changed files with 248 additions and 111 deletions
@ -0,0 +1,59 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYTREE_HH |
|||
#define PITYTEST_PITYTREE_HH |
|||
|
|||
//#include "../../../src/pEpLog.hh"
|
|||
#include <string> |
|||
#include <map> |
|||
#include <memory> |
|||
#include <unordered_map> |
|||
#include <functional> |
|||
#include <type_traits> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
template<class T> |
|||
class PityTree { |
|||
// TODO: NEEEEED THIS
|
|||
// static_assert(std::is_base_of<PityTree<T>, T>::value, "PityTree<T> must be a base of T");
|
|||
public: |
|||
using Children = std::map<const std::string, T&>; |
|||
|
|||
explicit PityTree(T& self, const std::string& name); |
|||
explicit PityTree(T& self, const std::string& name, T& parent); |
|||
|
|||
T& add(T& node); |
|||
|
|||
T* getParent() const; |
|||
Children getChildren() const; |
|||
|
|||
T& getRoot(); |
|||
|
|||
std::string getName() const; |
|||
std::string getPath() const; |
|||
bool isRoot() const; // true if has no parent
|
|||
|
|||
std::string to_string(bool recursive = true, int indent = 0); |
|||
|
|||
//TODO HACK in PityTransport, this should be private
|
|||
static std::string _normalizeName(std::string name); |
|||
|
|||
virtual ~PityTree() = default; |
|||
|
|||
protected: |
|||
void setParent(T* const parent); |
|||
|
|||
private: |
|||
// Fields
|
|||
const std::string _nodename; |
|||
T& _self; |
|||
T* _parent = nullptr; //nullptr if RootUnit
|
|||
Children _children; // map to guarantee uniqueness of sibling-names
|
|||
}; |
|||
}; // namespace PityTest11
|
|||
}; // namespace pEp
|
|||
|
|||
#include "PityTree.hxx" |
|||
#endif |
@ -0,0 +1,139 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYTREE_HXX |
|||
#define PITYTEST_PITYTREE_HXX |
|||
|
|||
#include <iostream> |
|||
#include <unistd.h> |
|||
#include <cstdlib> |
|||
#include <sys/stat.h> |
|||
#include <functional> |
|||
#include <algorithm> |
|||
#include <sstream> |
|||
#include <exception> |
|||
#include <memory> |
|||
#include <unordered_map> |
|||
#include <sys/wait.h> |
|||
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
|
|||
template<class T> |
|||
PityTree<T>::PityTree(T& self, const std::string &name) : |
|||
_self{ self }, _nodename{ _normalizeName(name) } |
|||
{ |
|||
} |
|||
|
|||
template<class T> |
|||
PityTree<T>::PityTree(T& self, const std::string &name, T& parent) : |
|||
_self(self), _nodename{ _normalizeName(name) } |
|||
{ |
|||
parent.add(_self); |
|||
} |
|||
|
|||
template<class T> |
|||
T& PityTree<T>::add(T& node) |
|||
{ |
|||
node.setParent(&_self); |
|||
_children.insert(std::pair<const std::string, T&>(node.getName(), node)); |
|||
return node; |
|||
} |
|||
|
|||
template<class T> |
|||
void PityTree<T>::setParent(T *parent) |
|||
{ |
|||
_parent = parent; |
|||
} |
|||
|
|||
template<class T> |
|||
T *PityTree<T>::getParent() const |
|||
{ |
|||
return _parent; |
|||
} |
|||
|
|||
template<class T> |
|||
bool PityTree<T>::isRoot() const |
|||
{ |
|||
if (_parent == nullptr) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
template<class T> |
|||
std::string PityTree<T>::getName() const |
|||
{ |
|||
return _nodename; |
|||
} |
|||
|
|||
template<class T> |
|||
std::string PityTree<T>::getPath() const |
|||
{ |
|||
std::string ret; |
|||
|
|||
if (!isRoot()) { |
|||
ret = _parent->getPath() + "/" + getName(); |
|||
} else { |
|||
ret = getName(); |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
template<class T> |
|||
std::string PityTree<T>::to_string(bool recursive, int indent) |
|||
{ |
|||
std::string ret; |
|||
std::stringstream builder; |
|||
builder << std::string(indent * 4, ' '); |
|||
builder << getName(); |
|||
builder << std::endl; |
|||
ret = builder.str(); |
|||
|
|||
if (recursive) { |
|||
if (!getChildren().empty()) { |
|||
indent++; |
|||
for (auto child : getChildren()) { |
|||
ret += child.second.to_string(true, indent); |
|||
} |
|||
indent--; |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
template<class T> |
|||
T& PityTree<T>::getRoot() |
|||
{ |
|||
if (!isRoot()) { |
|||
return _parent->getRoot(); |
|||
} else { |
|||
return _self; |
|||
} |
|||
} |
|||
|
|||
template<class T> |
|||
typename PityTree<T>::Children PityTree<T>::getChildren() const |
|||
{ |
|||
return _children; |
|||
} |
|||
|
|||
// name is alphanumeric only (everything else will be replaced by an underscore)
|
|||
// static
|
|||
template<class T> |
|||
std::string PityTree<T>::_normalizeName(std::string name) |
|||
{ |
|||
replace_if( |
|||
name.begin(), |
|||
name.end(), |
|||
[](char c) -> bool { return !isalnum(c); }, |
|||
'_'); |
|||
|
|||
return name; |
|||
} |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
|||
|
|||
#endif |
Loading…
Reference in new issue