From a14896f9ed209dd3f9597722e5a5697bd7dbf531 Mon Sep 17 00:00:00 2001 From: "Claudius \"keldu\" Holeksa" Date: Mon, 4 Dec 2023 12:18:14 +0100 Subject: meta: Renamed folder containing source --- modules/core/tree.h | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 modules/core/tree.h (limited to 'modules/core/tree.h') diff --git a/modules/core/tree.h b/modules/core/tree.h new file mode 100644 index 0000000..68fa20a --- /dev/null +++ b/modules/core/tree.h @@ -0,0 +1,248 @@ +#pragma once + +#include +#include + +#include "error.h" + +namespace saw { +/** + * Container with a simplistic approach to a branch + */ +template +class branch; + +/** + * Tree object holding branches. + * + * The name comes from the fact a tree is acting as a node while the branch class is the + * edge to a leaf or other nodes. A tree holds the branches while the branch either has + * a leaf or another sub tree. + */ +template +class tree_container final { +private: + /** + * Object holding the treeed branch instances + */ + std::vector> children_; +public: + /** + * Default constructor + */ + tree_container() = default; + + /** + * Destructor + */ + ~tree_container() = default; + + SAW_FORBID_COPY(tree_container); + SAW_DEFAULT_MOVE(tree_container); + + /** + * Reserve space for siz elements + */ + error_or reserve(std::size_t siz){ + try{ + children_.reserve(siz); + }catch(const std::exception& e){ + (void) e; + + return make_error(); + } + + return void_t{}; + } + + /** + * Add a branch with a leaf attached to the tree + */ + error_or add(T leaf) { + std::size_t index = size(); + try { + /** + * Technically we're adding a leaf on a branch + */ + children_.emplace_back(std::move(leaf)); + }catch(const std::exception& e){ + (void)e; + + return make_error(); + } + + return index; + } + + /** + * Add a branch to the tree with a tree attached + */ + error_or add() { + std::size_t index = size(); + try { + + children_.emplace_back(Tree{}); + }catch(const std::exception& e){ + (void)e; + + return make_error(); + } + + return index; + } + + /** + * Returns the amount of branches contained within this tree level + */ + std::size_t size() const { + return children_.size(); + } + + /** + * Returns the branch at i + */ + branch& at(std::size_t i){ + return children_.at(i); + } + + /** + * Returns the branch at i + */ + const branch& at(std::size_t i) const { + return children_.at(i); + } +}; + +template +class branch final { +private: + using type = std::variant; + type tov_; + + /** + * We're friend classing the tree since it's way easier this way and the branch and tree + * class are intertwined heavily anyway. + */ +public: + /** + * + */ + branch():tov_{Tree{}}{} + + branch(Tree nd):tov_{std::move(nd)}{} + + branch(T val):tov_{std::move(val)}{} + + SAW_FORBID_COPY(branch); + SAW_DEFAULT_MOVE(branch); + + template + bool is() const { + return std::holds_alternative(tov_); + } + + bool is_tree() const { + return std::holds_alternative(tov_); + } + + bool is_value() const { + return std::holds_alternative(tov_); + } + + template + NT& get() { + return std::get(tov_); + } + + template + const NT& get() const { + return std::get(tov_); + } + + Tree& get_tree(){ + return std::get(tov_); + } + + const Tree& get_tree() const { + return std::get(tov_); + } + + T& get_value(){ + return std::get(tov_); + } + + const T& get_value() const { + return std::get(tov_); + } + + template + error_or extract(){ + if(!is()){ + return make_error(); + } + + NT nd = std::move(std::get(tov_)); + tov_ = Tree{}; + + return nd; + } + + template + error_or replace(type nd){ + auto eon = extract(); + if(eon.is_error()){ + return eon; + } + + tov_ = std::move(nd); + + return eon; + } + + error_or extract_tree() { + return extract(); + } + + error_or replace_tree(type nd){ + return replace(std::move(nd)); + } + + error_or extract_value() { + return extract(); + } + + error_or replace_value(type nd){ + return replace(std::move(nd)); + } +}; + +template +class tree { + private: + tree_container> data_; + public: + error_or reserve(std::size_t size){ + return data_.reserve(size); + } + + size_t size() const { + return data_.size(); + } + + error_or add() { + return data_.add(); + } + + error_or add(T leaf){ + return data_.add(std::move(leaf)); + } + + branch>& at(size_t i){ + return data_.at(i); + } + + const branch>& at(size_t i) const { + return data_.at(i); + } +}; +} -- cgit v1.2.3