vxorg/vxorg.cpp

134 lines
2.7 KiB
C++
Raw Normal View History

#include <optional>
#include <string>
#include <vector>
#include <filesystem>
/// Port of tree.py to C++
template<class T>
struct Tree {
// FIXME make T not require default constructability
struct Node {
protected:
friend Tree;
Node* parent = nullptr;
std::vector<Node*> children{};
T item{};
public:
~Node() {
for(auto& child: children)
delete child;
}
T& data() {
return item;
}
const T& data() const {
return item;
}
bool is_leaf() const {
return children.size() == 0;
}
Node* create_leaf(const T& item) {
auto* node = new Node;
node->parent = this;
node->item = item;
children.push_back(node);
return node;
}
template<class Fn>
void walk(Fn&& fn) {
fn(this);
if(!is_leaf()) {
for(auto& child: children)
child->walk(fn);
}
}
template<class Pred>
std::optional<Node*> find_child(Pred&& predicate) {
if(predicate(*this))
return this;
for(auto& child: children)
if(predicate(*child))
return child;
return std::nullopt;
}
std::size_t parent_count() const {
auto* parent = this->parent;
auto parent_count = 0z;
while(parent) {
parent_count ++;
parent = parent->parent;
}
return parent_count;
}
};
Tree() {
root = new Node;
}
~Tree() {
delete root;
}
// Trees are not copyable but they can move
Tree(const Tree&) = delete;
Tree(Tree&&) = default;
template<class Fn>
void walk(Fn&& fn) {
root->walk(fn);
}
Node* create_leaf(const T& item) {
return root->create_leaf(item);
}
private:
Node* root;
};
void test_tree() {
Tree<std::string> tree;
auto* virus = tree.create_leaf("Virus");
auto* worm = tree.create_leaf("Worm");
auto* test = virus->create_leaf("test");
test->create_leaf("a");
test->create_leaf("b");
test->create_leaf("c");
test->create_leaf("884");
tree.walk([](auto* node) {
auto tab_count = node->parent_count();
auto& data = node->data();
for(auto i = 0; i < tab_count; ++i)
std::printf("\t");
if(data.empty()) {
std::printf("(root)\n");
} else {
std::printf("%s\n", data.c_str());
}
});
}
int main() {
test_tree();
return 0;
}