Files
Upsilon/apps/tree/tree_node.h
2018-07-02 15:48:50 +02:00

185 lines
5.2 KiB
C++

#ifndef TREE_NODE_H
#define TREE_NODE_H
#include <assert.h>
#include <stddef.h>
#include <strings.h>
#include <stdio.h>
/* What's in a TreeNode, really?
* - a vtable
* - an identifier
* - a reference counter
*/
class TreeNode {
friend class TreePool;
public:
virtual ~TreeNode() {}
// Attributes
virtual size_t size() const = 0;
int identifier() const { return m_identifier; }
int retainCount() const { return m_referenceCounter; }
void setReferenceCounter(int refCount) { m_referenceCounter = refCount; } //TODO make this method privte with only friends that can access it
void deepResetReferenceCounter() { //TODO make this method private with friends that can access it
setReferenceCounter(0);
for (TreeNode * t : depthFirstChildren()) {
t->setReferenceCounter(1);
}
}
virtual const char * description() const {
return "UNKNOWN";
}
virtual bool isAllocationFailure() const { return false; }
virtual TreeNode * failedAllocationStaticNode() {
assert(false);
return nullptr;
}
virtual int allocationFailureNodeIdentifier() {
assert(false);
return -1;
}
// Node operations
void retain() { m_referenceCounter++; }
void release();
void releaseChildren();
void releaseChildrenAndDestroy();
void rename(int identifier) {
m_identifier = identifier;
m_referenceCounter = 1;
}
// Hierarchy
TreeNode * parentTree() const;
TreeNode * editableRootTree();
virtual int numberOfChildren() const = 0;
virtual void incrementNumberOfChildren(int increment = 1) {} //TODO Put an assert false
virtual void decrementNumberOfChildren(int decrement = 1) {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ?
virtual void eraseNumberOfChildren() {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ?
int numberOfDescendants(bool includeSelf) const;
TreeNode * childTreeAtIndex(int i) const;
int indexOfChildByIdentifier(int childID) const;
int indexOfChild(const TreeNode * child) const;
int indexInParent() const;
bool hasChild(const TreeNode * child) const;
bool hasAncestor(const TreeNode * node, bool includeSelf) const;
bool hasSibling(const TreeNode * e) const;
class Iterator {
public:
Iterator(const TreeNode * node) : m_node(const_cast<TreeNode *>(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(const TreeNode * node) : m_node(const_cast<TreeNode *>(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;
};
class DepthFirst {
public:
DepthFirst(const TreeNode * node) : m_node(const_cast<TreeNode *>(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;
};
Direct directChildren() const { return Direct(this); }
DepthFirst depthFirstChildren() const { return DepthFirst(this); }
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;
}
// Hierarchy operations
void replaceWithAllocationFailure();
void addChildAtIndex(TreeNode * t, int index);
void removeChild(TreeNode * t);
protected:
TreeNode() :
m_identifier(-1),
m_referenceCounter(1)
{
}
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