mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-24 00:00:44 +01:00
181 lines
4.0 KiB
C++
181 lines
4.0 KiB
C++
#ifndef TREE_NODE_H
|
|
#define TREE_NODE_H
|
|
|
|
#include <assert.h>
|
|
#include <stddef.h>
|
|
#include <strings.h>
|
|
|
|
#define TREE_LOGGING 1
|
|
|
|
#include <stdio.h>
|
|
|
|
/* What's in a TreeNode, really?
|
|
* - a vtable
|
|
* - an identifier
|
|
* - a reference counter
|
|
*/
|
|
|
|
class TreeNode {
|
|
//friend class TreeReference;
|
|
// friend class TreePool;
|
|
public:
|
|
virtual ~TreeNode() {
|
|
}
|
|
|
|
// Iterators
|
|
|
|
class Iterator {
|
|
public:
|
|
Iterator(TreeNode * node) : m_node(node) {}
|
|
TreeNode * operator*() { return m_node; }
|
|
bool operator!=(const Iterator& it) const { return (m_node != it.m_node); }
|
|
protected:
|
|
TreeNode * m_node;
|
|
};
|
|
|
|
class Direct {
|
|
public:
|
|
Direct(TreeNode * node) : m_node(node) {}
|
|
class Iterator : public TreeNode::Iterator {
|
|
public:
|
|
using TreeNode::Iterator::Iterator;
|
|
Iterator & operator++() {
|
|
m_node = m_node->nextSibling();
|
|
return *this;
|
|
}
|
|
};
|
|
Iterator begin() const { return Iterator(m_node->next()); }
|
|
Iterator end() const { return Iterator(m_node->nextSibling()); }
|
|
private:
|
|
TreeNode * m_node;
|
|
};
|
|
|
|
Direct directChildren() { return Direct(this); }
|
|
|
|
class DepthFirst {
|
|
public:
|
|
DepthFirst(TreeNode * node) : m_node(node) {}
|
|
class Iterator : public TreeNode::Iterator {
|
|
public:
|
|
using TreeNode::Iterator::Iterator;
|
|
Iterator & operator++() {
|
|
m_node = m_node->next();
|
|
return *this;
|
|
}
|
|
};
|
|
Iterator begin() const { return Iterator(m_node->next()); }
|
|
Iterator end() const { return Iterator(m_node->nextSibling()); }
|
|
private:
|
|
TreeNode * m_node;
|
|
};
|
|
|
|
DepthFirst depthFirstChildren() { return DepthFirst(this); }
|
|
|
|
|
|
int identifier() const { return m_identifier; }
|
|
|
|
#if TREE_LOGGING
|
|
virtual const char * description() const {
|
|
return "UNKNOWN";
|
|
}
|
|
#endif
|
|
|
|
virtual size_t size() const { // Consider making this full abstract?
|
|
return sizeof(TreeNode);
|
|
}
|
|
|
|
void retain() {
|
|
m_referenceCounter++;
|
|
}
|
|
|
|
void release();
|
|
|
|
void rename(int identifier) {
|
|
m_identifier = identifier;
|
|
m_referenceCounter = 1;
|
|
}
|
|
|
|
int retainCount() {
|
|
return m_referenceCounter;
|
|
}
|
|
|
|
virtual int numberOfChildren() const {
|
|
return 0;
|
|
}
|
|
|
|
TreeNode * childAtIndex(int i) const {
|
|
assert(i >= 0);
|
|
assert(i < numberOfChildren());
|
|
TreeNode * child = next();
|
|
while (i > 0) {
|
|
child = child->nextSibling();
|
|
assert(child != nullptr);
|
|
i--;
|
|
}
|
|
return child;
|
|
}
|
|
|
|
//private:
|
|
|
|
// FIXME: Make this private
|
|
TreeNode(int identifier) :
|
|
m_identifier(identifier),
|
|
m_referenceCounter(1)
|
|
{
|
|
}
|
|
|
|
TreeNode * next() const {
|
|
// Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler.
|
|
// Unfortunately, we want TreeNode to have a VARIABLE size
|
|
return reinterpret_cast<TreeNode *>(reinterpret_cast<char *>(const_cast<TreeNode *>(this)) + size());
|
|
}
|
|
|
|
TreeNode * nextSibling() const {
|
|
int remainingNodesToVisit = numberOfChildren();
|
|
TreeNode * node = const_cast<TreeNode *>(this)->next();
|
|
while (remainingNodesToVisit > 0) {
|
|
remainingNodesToVisit += node->numberOfChildren();
|
|
node = node->next();
|
|
remainingNodesToVisit--;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
/*TreeNode * lastDescendant() const {
|
|
TreeNode * node = const_cast<TreeNode *>(this);
|
|
int remainingNodesToVisit = node->numberOfChildren();
|
|
while (remainingNodesToVisit > 0) {
|
|
node = node->next();
|
|
remainingNodesToVisit--;
|
|
remainingNodesToVisit += node->numberOfChildren();
|
|
}
|
|
return node;
|
|
}*/
|
|
|
|
TreeNode * lastChild() const {
|
|
if (numberOfChildren() == 0) {
|
|
return const_cast<TreeNode *>(this);
|
|
}
|
|
TreeNode * node = next();
|
|
for (int i = 0; i < numberOfChildren() - 1; i++) {
|
|
node = node->nextSibling();
|
|
}
|
|
return node;
|
|
}
|
|
|
|
size_t deepSize() const {
|
|
// TODO: Error handling
|
|
return
|
|
reinterpret_cast<char *>(nextSibling())
|
|
-
|
|
reinterpret_cast<const char *>(this);
|
|
;
|
|
}
|
|
|
|
//private:
|
|
int m_identifier;
|
|
int m_referenceCounter;
|
|
};
|
|
|
|
#endif
|