
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