#include #include #include namespace Poincare { // Node operations void TreeNode::release(int currentNumberOfChildren) { m_referenceCounter--; if (m_referenceCounter == 0) { deleteParentIdentifierInChildren(); TreePool::sharedPool()->removeChildrenAndDestroy(this, currentNumberOfChildren); } } void TreeNode::rename(uint16_t identifier, bool unregisterPreviousIdentifier) { if (unregisterPreviousIdentifier) { /* The previous identifier should not always be unregistered. For instance, * if the node is a clone and still has the original node's identifier, * unregistering it would lose the access to the original node. */ TreePool::sharedPool()->unregisterNode(this); } m_identifier = identifier; m_referenceCounter = 0; TreePool::sharedPool()->registerNode(this); updateParentIdentifierInChildren(); } // Hierarchy TreeNode * TreeNode::parent() const { assert(m_parentIdentifier != m_identifier); return TreeHandle::hasNode(m_parentIdentifier) ? TreePool::sharedPool()->node(m_parentIdentifier) : nullptr; } TreeNode * TreeNode::root() { TreeNode * result = this; TreeNode * resultParent = result->parent(); while(resultParent != nullptr) { result = resultParent; resultParent = result->parent(); } return result; } int TreeNode::numberOfDescendants(bool includeSelf) const { int result = includeSelf ? 1 : 0; TreeNode * nextSiblingNode = nextSibling(); TreeNode * currentNode = next(); while (currentNode != nextSiblingNode) { result++; currentNode = currentNode->next(); } return result; } TreeNode * TreeNode::childAtIndex(int i) const { assert(i >= 0); assert(i < numberOfChildren()); TreeNode * child = next(); while (i > 0) { child = child->nextSibling(); assert(child != nullptr); i--; } assert(m_identifier != child->identifier()); return child; } int TreeNode::indexOfChild(const TreeNode * child) const { assert(child != nullptr); int childrenCount = numberOfChildren(); TreeNode * childAtIndexi = next(); for (int i = 0; i < childrenCount; i++) { if (childAtIndexi == child) { return i; } childAtIndexi = childAtIndexi->nextSibling(); } return -1; } int TreeNode::indexInParent() const { TreeNode * p = parent(); if (p == nullptr) { return -1; } return p->indexOfChild(this); } bool TreeNode::hasChild(const TreeNode * child) const { for (TreeNode * c : directChildren()) { if (child == c) { return true; } } return false; } bool TreeNode::hasAncestor(const TreeNode * node, bool includeSelf) const { if (includeSelf && node == this) { return true; } for (TreeNode * t : node->depthFirstChildren()) { if (this == t) { return true; } } return false; } bool TreeNode::hasSibling(const TreeNode * e) const { TreeNode * p = parent(); if (p == nullptr) { return false; } for (TreeNode * childNode : p->directChildren()) { if (childNode == e) { return true; } } return false; } TreeNode * TreeNode::nextSibling() const { int remainingNodesToVisit = numberOfChildren(); TreeNode * node = const_cast(this)->next(); while (remainingNodesToVisit > 0) { remainingNodesToVisit += node->numberOfChildren(); node = node->next(); remainingNodesToVisit--; } return node; } TreeNode * TreeNode::lastDescendant() const { TreeNode * node = const_cast(this); int remainingNodesToVisit = node->numberOfChildren(); while (remainingNodesToVisit > 0) { node = node->next(); remainingNodesToVisit--; remainingNodesToVisit += node->numberOfChildren(); } return node; } // Protected #if POINCARE_TREE_LOG void TreeNode::log(std::ostream & stream, bool recursive) { stream << "<"; logNodeName(stream); stream << " id=\"" << m_identifier << "\""; stream << " refCount=\"" << (int16_t)m_referenceCounter << "\""; stream << " size=\"" << size() << "\""; logAttributes(stream); stream << ">"; if (recursive) { for (TreeNode * child : directChildren()) { child->log(stream, recursive); } } stream << ""; } #endif size_t TreeNode::deepSize(int realNumberOfChildren) const { if (realNumberOfChildren == -1) { return reinterpret_cast(nextSibling()) - reinterpret_cast(this); } TreeNode * realNextSibling = next(); for (int i = 0; i < realNumberOfChildren; i++) { realNextSibling = realNextSibling->nextSibling(); } return reinterpret_cast(realNextSibling) - reinterpret_cast(this); } void TreeNode::changeParentIdentifierInChildren(uint16_t id) const { for (TreeNode * c : directChildren()) { c->setParentIdentifier(id); } } }