diff options
-rw-r--r-- | c++/core/tree.h | 152 | ||||
-rw-r--r-- | tests/codec.cpp | 2 | ||||
-rw-r--r-- | tests/tree.cpp | 38 |
3 files changed, 191 insertions, 1 deletions
diff --git a/c++/core/tree.h b/c++/core/tree.h new file mode 100644 index 0000000..6ffd1f0 --- /dev/null +++ b/c++/core/tree.h @@ -0,0 +1,152 @@ +#pragma once + +#include <variant> +#include <vector> + +#include "error.h" + +namespace saw { +template<typename T> +class tree_or; + +template<typename T> +class tree final { +private: + std::vector<tree_or<T>> children_; +public: + tree() = default; + ~tree() = default; + + error_or<std::size_t> add(T leaf) { + std::size_t index = size(); + try { + children_.push_back(std::move(leaf)); + }catch(const std::exception& e){ + (void)e; + + return make_error<err::critical>(); + } + + return index; + } + + error_or<std::size_t> add() { + std::size_t index = size(); + try { + children_.push_back(tree{}); + }catch(const std::exception& e){ + (void)e; + + return make_error<err::critical>(); + } + + return index; + } + + std::size_t size() const { + return children_.size(); + } + + tree_or<T>& at(std::size_t i){ + return children_.at(i); + } + + const tree_or<T>& at(std::size_t i) const { + return children_.at(i); + } +}; + +template<typename T> +class tree_or final { +private: + using type = std::variant<tree<T>,T>; + type tov_; + + friend class tree<T>; +public: + tree_or():tov_{tree<T>{}}{} + + tree_or(tree<T> nd):tov_{std::move(nd)}{} + + tree_or(T val):tov_{std::move(val)}{} + + template<typename NT> + bool is() const { + return std::holds_alternative<NT>(tov_); + } + + bool is_tree() const { + return std::holds_alternative<tree>(tov_); + } + + bool is_value() const { + return std::holds_alternative<T>(tov_); + } + + template<typename NT> + NT& get() { + return std::get<NT>(tov_); + } + + template<typename NT> + const NT& get() const { + return std::get<NT>(tov_); + } + + tree<T>& get_tree(){ + return std::get<tree>(tov_); + } + + const tree<T>& get_tree() const { + return std::get<tree>(tov_); + } + + T& get_value(){ + return std::get<T>(tov_); + } + + const T& get_value() const { + return std::get<T>(tov_); + } + + template<typename NT> + error_or<NT> extract(){ + if(!is<NT>()){ + return make_error<err::invalid_state>(); + } + + NT nd = std::move(std::get<NT>(tov_)); + tov_ = tree<T>{}; + + return nd; + } + + template<typename NT> + error_or<NT> replace(type nd){ + auto eon = extract<NT>(); + if(eon.is_error()){ + return eon; + } + + tov_ = std::move(nd); + + return eon; + } + + error_or<tree<T>> extract_tree() { + return extract<tree<T>>(); + } + + error_or<tree<T>> replace_tree(type nd){ + return replace<tree<T>>(std::move(nd)); + } + + error_or<T> extract_value() { + return extract<T>(); + } + + error_or<T> replace_value(type nd){ + return replace<T>(std::move(nd)); + } +}; +} diff --git a/tests/codec.cpp b/tests/codec.cpp index 439332a..f3e27f5 100644 --- a/tests/codec.cpp +++ b/tests/codec.cpp @@ -1,7 +1,7 @@ #include <forstio/test/suite.h> #include <forstio/codec/data.h> #include <forstio/codec/simple.h> -#include <forstio/codec/rpc.h> +#include <forstio/codec/interface.h> #include <iostream> diff --git a/tests/tree.cpp b/tests/tree.cpp new file mode 100644 index 0000000..de6bda6 --- /dev/null +++ b/tests/tree.cpp @@ -0,0 +1,38 @@ +#include <forstio/test/suite.h> +#include <forstio/core/tree.h> + +namespace { +SAW_TEST("Tree insert"){ + using namespace saw; + + tree_or<int> troi; + { + // Replace with value + auto eor = troi.replace_tree(5); + + SAW_EXPECT(eor.is_value(), "Didn't manage to replace with value"); + } + { + // Replace with tree again + auto eor = troi.replace_value(tree<int>{}); + + SAW_EXPECT(eor.is_value(), "Not a value"); + } +} + +SAW_TEST("Tree add child"){ + using namespace saw; + + tree<int> tr; + { + auto eov = tr.add(10); + SAW_EXPECT(eov.is_value(), "Didn't manage to add value"); + } + { + auto eov = tr.add(); + SAW_EXPECT(eov.is_value(), "Didn't manage to add tree"); + std::size_t index = eov.get_value(); + + } +} +} |