diff --git a/etk/FlatTree.hpp b/etk/FlatTree.hpp new file mode 100644 index 0000000..950b77f --- /dev/null +++ b/etk/FlatTree.hpp @@ -0,0 +1,231 @@ +/** + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL-2 (see license file) + */ +#pragma once + +#include +//#include +#include +#include +#include + +namespace etk { + template class FlatTree { + public: + # if 0 + //static const size_t npos = size_t(-1); + class Iterator { + private: + size_t m_current; //!< current Id on the vector + FlatTree* m_tree; //!< Pointer on the current element of the vectorBin + public: + /** + * @brief Basic iterator constructor with no link with an etk::Vector + */ + Iterator(): + m_current(0), + m_tree(null) { + // nothing to do ... + } + /** + * @brief Recopy constructor on a specific etkVector. + * @param[in] _obj The Iterator that might be copy + */ + Iterator(const Iterator & _obj): + m_current(_obj.m_current), + m_tree(_obj.m_tree) { + // nothing to do ... + } + /** + * @brief Assignation operator. + * @param[in] _otherIterator The Iterator that might be copy + * @return reference on the current Iterator + */ + Iterator& operator=(const Iterator & _otherIterator) { + m_current = _otherIterator.m_current; + m_tree = _otherIterator.m_tree; + return *this; + } + /** + * @brief Basic destructor + */ + ~Iterator() { + m_current = 0; + m_tree = null; + } + /** + * @brief basic boolean cast + * @return true if the element is present in the etkVector size + */ + operator bool () { + return (m_current < m_tree->size()); + } + /** + * @brief != Comparaison operator + * @param[in] _obj Object to compare + * @return true if the element are different + */ + bool operator!= (const Iterator& _obj) { + if ( m_tree != _obj.m_tree + || m_current != _obj.m_current) { + return true; + } + return false; + } + /** + * @brief == Comparaison operator. + * @param[in] _obj Object to compare. + * @return true if the element are identical. + */ + bool operator== (const Iterator& _obj) { + if ( m_tree == _obj.m_tree + && m_current == _obj.m_current) { + return true; + } + return false; + } + /** + * @brief Incremental operator + * @return Reference on the current iterator increment + */ + Iterator& operator++ () { + if ( m_tree != null + && m_current < m_tree->size() ) + { + m_current++; + } + return *this; + } + /** + * @brief Decremental operator + * @return Reference on the current iterator decrement + */ + Iterator& operator-- () { + if ( m_tree != null + && m_current > 0) { + m_current--; + } + return *this; + } + /** + * @brief Incremental operator + * @return Reference on a new iterator and increment the other one + */ + Iterator operator++ (int32_t) { + Iterator it(*this); + ++(*this); + return it; + } + /** + * @brief Decremental operator + * @return Reference on a new iterator and decrement the other one + */ + Iterator operator-- (int32_t) { + Iterator it(*this); + --(*this); + return it; + } + Iterator& operator-= (size_t _offset) { + m_current -= _offset; + return *this; + } + Iterator operator- (size_t _offset) const { + Iterator tmp(*this); + tmp -= _offset; + return tmp; + } + Iterator& operator-= (int _offset) { + m_current -= _offset; + return *this; + } + Iterator operator- (int _offset) const { + Iterator tmp(*this); + tmp -= _offset; + return tmp; + } + Iterator& operator-= (int64_t _offset) { + m_current -= _offset; + return *this; + } + Iterator operator- (int64_t _offset) const { + Iterator tmp(*this); + tmp -= _offset; + return tmp; + } + Iterator& operator+= (size_t _offset) { + m_current += _offset; + return *this; + } + Iterator operator+ (size_t _offset) const { + Iterator tmp(*this); + tmp += _offset; + return tmp; + } + Iterator& operator+= (int _offset) { + m_current += _offset; + return *this; + } + Iterator operator+ (int _offset) const { + Iterator tmp(*this); + tmp += _offset; + return tmp; + } + Iterator& operator+= (int64_t _offset) { + m_current += _offset; + return *this; + } + Iterator operator+ (int64_t _offset) const { + Iterator tmp(*this); + tmp += _offset; + return tmp; + } + /** + * @brief Get reference on the current Element + * @return the reference on the current Element + */ + ETK_TREENODE_TYPE* operator-> () const { + return &m_tree->get(m_current); + } + /** + * @brief Get reference on the current Element + * @return the reference on the current Element + */ + ETK_TREENODE_TYPE& operator* () const { + return m_tree->get(m_current); + } + private: + Iterator(const FlatTree * _obj, int32_t _pos): + m_current(_pos), + m_tree(const_cast *>(_obj)) { + // nothing to do ... + } + size_t getCurrent() const { + return m_current; + } + friend class FlatTree; + }; + #endif + private: + etk::Vector>> m_data; + public: + FlatTree() { + + } + void setRoot(const ememory::SharedPtr>& _root) { + m_data.clear(); + append(_root); + } + private: + void append(const ememory::SharedPtr>& _node) { + if (_node == null) { + return; + } + m_data.pushBack(_node); + for (auto& it:_node->getChilds()) { + append(it); + } + } + }; +} diff --git a/etk/TreeNode.hpp b/etk/TreeNode.hpp new file mode 100644 index 0000000..d5cf3aa --- /dev/null +++ b/etk/TreeNode.hpp @@ -0,0 +1,129 @@ +/** + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL-2 (see license file) + */ +#pragma once + +#include +//#include +#include +#include +#include +#include +#include + +namespace etk { + template class TreeNode : public ememory::EnableSharedFromThis> { + public: + TreeNode(ETK_TREENODE_TYPE&& _data): + m_data(_data) { + + } + ETK_CONSTRUCTOR_MOVE_DELETE(TreeNode); + ETK_CONSTRUCTOR_COPY_DELETE(TreeNode); + static ememory::SharedPtr create(ETK_TREENODE_TYPE&& _data) { + return ememory::makeShared(etk::forward(_data)); + } + private: + ememory::WeakPtr> m_parent; + public: + ememory::SharedPtr> getParent() const { + return m_parent.lock(); + } + void setParent(const ememory::SharedPtr>& _parent) { + if (_parent == m_parent.lock()) { + return; + } + if (m_parent != null) { + ETK_THROW_EXCEPTION(etk::exception::RuntimeError("Set a treeNode parrent on an already used treeNode")); + } + m_parent = _parent; + } + bool haveParent() const { + if (getParent() == null) { + return false; + } + return true; + } + public: + using Childs = etk::Vector>; + private: + Childs m_childs; //!< List of child in this node + public: + /** + * @brief Get child list. + * @return The child inteface. + */ + const Childs& getChilds() const { + return m_childs; + } + Childs& getChilds() { + return m_childs; + } + void addChild(ememory::SharedPtr _child) { + if (_child == null) { + return; + } + for (auto& it: m_childs) { + if (it == _child) { + return; + } + } + _child->setParent(ememory::EnableSharedFromThis>::sharedFromThis()); + m_childs.pushBack(_child); + } + void rmChild(ememory::SharedPtr _child) { + if (_child == null) { + return; + } + auto it = m_childs.begin(); + while (it != m_childs.end()) { + if (*it == _child) { + it->setParent(null); + m_childs.erase(it); + return; + } + ++it; + } + ETK_THROW_EXCEPTION(etk::exception::RuntimeError("Remove treeNode child that does not exist")); + } + void clear() { + for (auto& it: m_childs) { + it.setParent(null); + } + m_childs.clear(); + } + bool haveChild() const { + return m_childs.size() != 0; + } + size_t countChild() const { + return m_childs.size(); + } + private: + ETK_TREENODE_TYPE m_data; + public: + const ETK_TREENODE_TYPE& getData() const { + return m_data; + } + ETK_TREENODE_TYPE& getData() { + return m_data; + } + public: + using ConditionFunction = etk::Function; + etk::Vector> findIf(const ConditionFunction& findCondition) const { + etk::Vector> out; + if (findCondition(*this) == true) { + out.pushBack(ememory::EnableSharedFromThis>::sharedFromThis()); + } + for (auto& it: m_childs) { + auto ret = it->findIf(findCondition); + for (auto& element: ret) { + out.pushBack(element); + } + } + return out; + } + }; +} + diff --git a/lutin_etk-base.py b/lutin_etk-base.py index c7cac54..799bfc4 100644 --- a/lutin_etk-base.py +++ b/lutin_etk-base.py @@ -58,7 +58,7 @@ def configure(target, my_module): 'etk/Function.hpp', 'etk/NullPtr.hpp', 'etk/typeInfo.hpp', - 'etk/Exception.hpp', + 'etk/Exception.hpp' ]) # build in C++ mode diff --git a/lutin_etk.py b/lutin_etk.py index 14abe1b..4a4c09d 100644 --- a/lutin_etk.py +++ b/lutin_etk.py @@ -69,7 +69,10 @@ def configure(target, my_module): 'etk/os/FSNode.hpp', 'etk/os/FSNodeRight.hpp', 'etk/archive/Archive.hpp', - 'etk/archive/Zip.hpp']) + 'etk/archive/Zip.hpp', + 'etk/TreeNode.hpp', + 'etk/FlatTree.hpp', + ]) # build in C++ mode my_module.compile_version("c++", 2011)