#ifndef TREE_REFERENCE_H #define TREE_REFERENCE_H #include "tree_pool.h" #include static inline int min(int i, int j) { return i < j ? i : j; } static inline int max(int i, int j) { return i > j ? i : j; } class Cursor; template class TreeReference { friend class Cursor; public: TreeReference(const TreeReference & tr) { int trNodeIdentifier = tr.identifier(); TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(TreePool::sharedPool()->node(trNodeIdentifier)); m_identifier = nodeCopy->identifier(); } ~TreeReference() { assert(node()); printf("Delete TreeReference of m_id %d, nodeId %d\n", m_identifier, node()->identifier()); assert(node()->identifier() == m_identifier); node()->release(); } bool isDefined() const { return m_identifier >= 0 && TreePool::sharedPool()->node(m_identifier) != nullptr; } operator TreeReference() const { // TODO: make sure this is kosher // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); return *(reinterpret_cast *>(this)); } T * node() const { // TODO: Here, assert that the node type is indeed T return static_cast(TreePool::sharedPool()->node(m_identifier)); } int identifier() const { return m_identifier; } Cursor cursor(); // Hierarchy int numberOfChildren() const { return node()->numberOfChildren(); } TreeReference parent() const { return TreeReference(node()->parentTree()); } TreeReference childAtIndex(int i) const { return TreeReference(node()->child(i)); } // Hierarchy operations void addChild(TreeReference t) { TreeNode * deepCopy = TreePool::sharedPool()->deepCopy(t.node()); TreePool::sharedPool()->move(deepCopy, node()->next()); } void removeChild(TreeReference t) { TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); t.node()->release(); } void replaceWith(TreeReference t) { parent().replaceChild(node()->indexOfChild(t.node()), t); } void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); TreeReference oldChild = childAtIndex(oldChildIndex); TreePool::sharedPool()->move(newChild.node(), oldChild.node()->next()); newChild.node()->retain(); TreePool::sharedPool()->move(oldChild.node(), TreePool::sharedPool()->last()); oldChild.node()->release(); } void swapChildren(int i, int j) { assert(i >= 0 && i < numberOfChildren()); assert(j >= 0 && j < numberOfChildren()); if (i == j) { return; } int firstChildIndex = min(i, j); int secondChildIndex = max(i, j); TreeReference firstChild = childAtIndex(firstChildIndex); TreeReference secondChild = childAtIndex(secondChildIndex); TreeNode * firstChildNode = firstChild.node(); TreePool::sharedPool()->move(firstChildNode, secondChild.node()->next()); TreePool::sharedPool()->move(secondChild.node(), firstChildNode); } protected: TreeReference() { TreeNode * node = TreePool::sharedPool()->createTreeNode(); m_identifier = node->identifier(); } TreeReference(TreeNode * node) : m_identifier(node->identifier()) { node->retain(); } int m_identifier; }; #endif