[DEV] add a basic tree and flatTree
This commit is contained in:
parent
6194efaac4
commit
1026219ed2
231
etk/FlatTree.hpp
Normal file
231
etk/FlatTree.hpp
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL-2 (see license file)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <etk/types.hpp>
|
||||||
|
//#include <etk/debug.hpp>
|
||||||
|
#include <etk/Stream.hpp>
|
||||||
|
#include <etk/Allocator.hpp>
|
||||||
|
#include <etk/TreeNode.hpp>
|
||||||
|
|
||||||
|
namespace etk {
|
||||||
|
template<class ETK_TREENODE_TYPE> 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<ETK_TREENODE_TYPE>* 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<ETK_TREENODE_TYPE> * _obj, int32_t _pos):
|
||||||
|
m_current(_pos),
|
||||||
|
m_tree(const_cast<FlatTree<ETK_TREENODE_TYPE> *>(_obj)) {
|
||||||
|
// nothing to do ...
|
||||||
|
}
|
||||||
|
size_t getCurrent() const {
|
||||||
|
return m_current;
|
||||||
|
}
|
||||||
|
friend class FlatTree;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
etk::Vector<const ememory::SharedPtr<etk::TreeNode<ETK_TREENODE_TYPE>>> m_data;
|
||||||
|
public:
|
||||||
|
FlatTree() {
|
||||||
|
|
||||||
|
}
|
||||||
|
void setRoot(const ememory::SharedPtr<etk::TreeNode<ETK_TREENODE_TYPE>>& _root) {
|
||||||
|
m_data.clear();
|
||||||
|
append(_root);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void append(const ememory::SharedPtr<etk::TreeNode<ETK_TREENODE_TYPE>>& _node) {
|
||||||
|
if (_node == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_data.pushBack(_node);
|
||||||
|
for (auto& it:_node->getChilds()) {
|
||||||
|
append(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
129
etk/TreeNode.hpp
Normal file
129
etk/TreeNode.hpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL-2 (see license file)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <etk/types.hpp>
|
||||||
|
//#include <etk/debug.hpp>
|
||||||
|
#include <etk/Stream.hpp>
|
||||||
|
#include <etk/Allocator.hpp>
|
||||||
|
#include <etk/Function.hpp>
|
||||||
|
#include <ememory/SharedPtr.hpp>
|
||||||
|
#include <ememory/EnableSharedFromThis.hpp>
|
||||||
|
|
||||||
|
namespace etk {
|
||||||
|
template<class ETK_TREENODE_TYPE> class TreeNode : public ememory::EnableSharedFromThis<TreeNode<ETK_TREENODE_TYPE>> {
|
||||||
|
public:
|
||||||
|
TreeNode(ETK_TREENODE_TYPE&& _data):
|
||||||
|
m_data(_data) {
|
||||||
|
|
||||||
|
}
|
||||||
|
ETK_CONSTRUCTOR_MOVE_DELETE(TreeNode);
|
||||||
|
ETK_CONSTRUCTOR_COPY_DELETE(TreeNode);
|
||||||
|
static ememory::SharedPtr<TreeNode> create(ETK_TREENODE_TYPE&& _data) {
|
||||||
|
return ememory::makeShared<TreeNode>(etk::forward<ETK_TREENODE_TYPE>(_data));
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ememory::WeakPtr<TreeNode<ETK_TREENODE_TYPE>> m_parent;
|
||||||
|
public:
|
||||||
|
ememory::SharedPtr<TreeNode<ETK_TREENODE_TYPE>> getParent() const {
|
||||||
|
return m_parent.lock();
|
||||||
|
}
|
||||||
|
void setParent(const ememory::SharedPtr<TreeNode<ETK_TREENODE_TYPE>>& _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<ememory::SharedPtr<TreeNode>>;
|
||||||
|
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<TreeNode> _child) {
|
||||||
|
if (_child == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto& it: m_childs) {
|
||||||
|
if (it == _child) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_child->setParent(ememory::EnableSharedFromThis<TreeNode<ETK_TREENODE_TYPE>>::sharedFromThis());
|
||||||
|
m_childs.pushBack(_child);
|
||||||
|
}
|
||||||
|
void rmChild(ememory::SharedPtr<TreeNode> _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<bool(const TreeNode&)>;
|
||||||
|
etk::Vector<ememory::SharedPtr<TreeNode>> findIf(const ConditionFunction& findCondition) const {
|
||||||
|
etk::Vector<ememory::SharedPtr<TreeNode>> out;
|
||||||
|
if (findCondition(*this) == true) {
|
||||||
|
out.pushBack(ememory::EnableSharedFromThis<TreeNode<ETK_TREENODE_TYPE>>::sharedFromThis());
|
||||||
|
}
|
||||||
|
for (auto& it: m_childs) {
|
||||||
|
auto ret = it->findIf(findCondition);
|
||||||
|
for (auto& element: ret) {
|
||||||
|
out.pushBack(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ def configure(target, my_module):
|
|||||||
'etk/Function.hpp',
|
'etk/Function.hpp',
|
||||||
'etk/NullPtr.hpp',
|
'etk/NullPtr.hpp',
|
||||||
'etk/typeInfo.hpp',
|
'etk/typeInfo.hpp',
|
||||||
'etk/Exception.hpp',
|
'etk/Exception.hpp'
|
||||||
])
|
])
|
||||||
|
|
||||||
# build in C++ mode
|
# build in C++ mode
|
||||||
|
@ -69,7 +69,10 @@ def configure(target, my_module):
|
|||||||
'etk/os/FSNode.hpp',
|
'etk/os/FSNode.hpp',
|
||||||
'etk/os/FSNodeRight.hpp',
|
'etk/os/FSNodeRight.hpp',
|
||||||
'etk/archive/Archive.hpp',
|
'etk/archive/Archive.hpp',
|
||||||
'etk/archive/Zip.hpp'])
|
'etk/archive/Zip.hpp',
|
||||||
|
'etk/TreeNode.hpp',
|
||||||
|
'etk/FlatTree.hpp',
|
||||||
|
])
|
||||||
|
|
||||||
# build in C++ mode
|
# build in C++ mode
|
||||||
my_module.compile_version("c++", 2011)
|
my_module.compile_version("c++", 2011)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user