| // Copyright 2017 PDFium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 
 |  | 
 | #ifndef XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_ | 
 | #define XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_ | 
 |  | 
 | #include "core/fxcrt/unowned_ptr.h" | 
 | #include "v8/include/cppgc/macros.h" | 
 |  | 
 | template <class NodeType, | 
 |           class TraverseStrategy, | 
 |           typename HolderType = UnownedPtr<NodeType>> | 
 | class CXFA_NodeIteratorTemplate { | 
 |   CPPGC_STACK_ALLOCATED();  // Allows Raw/Unowned |HolderType|. | 
 |  | 
 |  public: | 
 |   explicit CXFA_NodeIteratorTemplate(NodeType* pRoot) | 
 |       : m_pRoot(pRoot), m_pCurrent(pRoot) {} | 
 |  | 
 |   NodeType* GetRoot() const { return static_cast<NodeType*>(m_pRoot); } | 
 |   NodeType* GetCurrent() const { return static_cast<NodeType*>(m_pCurrent); } | 
 |  | 
 |   void Reset() { m_pCurrent = m_pRoot; } | 
 |   bool SetCurrent(NodeType* pNode) { | 
 |     if (!RootReachableFromNode(pNode)) { | 
 |       m_pCurrent = nullptr; | 
 |       return false; | 
 |     } | 
 |     m_pCurrent = pNode; | 
 |     return true; | 
 |   } | 
 |  | 
 |   NodeType* MoveToPrev() { | 
 |     if (!m_pRoot) | 
 |       return nullptr; | 
 |     if (!m_pCurrent) { | 
 |       m_pCurrent = LastDescendant(static_cast<NodeType*>(m_pRoot)); | 
 |       return static_cast<NodeType*>(m_pCurrent); | 
 |     } | 
 |     NodeType* pSibling = | 
 |         PreviousSiblingWithinSubtree(static_cast<NodeType*>(m_pCurrent)); | 
 |     if (pSibling) { | 
 |       m_pCurrent = LastDescendant(pSibling); | 
 |       return static_cast<NodeType*>(m_pCurrent); | 
 |     } | 
 |     NodeType* pParent = ParentWithinSubtree(static_cast<NodeType*>(m_pCurrent)); | 
 |     if (pParent) | 
 |       m_pCurrent = pParent; | 
 |     return pParent; | 
 |   } | 
 |  | 
 |   NodeType* MoveToNext() { | 
 |     if (!m_pRoot || !m_pCurrent) | 
 |       return nullptr; | 
 |     NodeType* pChild = | 
 |         TraverseStrategy::GetFirstChild(static_cast<NodeType*>(m_pCurrent)); | 
 |     if (pChild) { | 
 |       m_pCurrent = pChild; | 
 |       return pChild; | 
 |     } | 
 |     return SkipChildrenAndMoveToNext(); | 
 |   } | 
 |  | 
 |   NodeType* SkipChildrenAndMoveToNext() { | 
 |     if (!m_pRoot) | 
 |       return nullptr; | 
 |     NodeType* pNode = static_cast<NodeType*>(m_pCurrent); | 
 |     while (pNode) { | 
 |       NodeType* pSibling = NextSiblingWithinSubtree(pNode); | 
 |       if (pSibling) { | 
 |         m_pCurrent = pSibling; | 
 |         return pSibling; | 
 |       } | 
 |       pNode = ParentWithinSubtree(pNode); | 
 |     } | 
 |     m_pCurrent = nullptr; | 
 |     return nullptr; | 
 |   } | 
 |  | 
 |  private: | 
 |   bool RootReachableFromNode(NodeType* pNode) { | 
 |     return pNode && (pNode == m_pRoot || | 
 |                      RootReachableFromNode(TraverseStrategy::GetParent(pNode))); | 
 |   } | 
 |  | 
 |   NodeType* ParentWithinSubtree(NodeType* pNode) { | 
 |     return pNode && pNode != m_pRoot ? TraverseStrategy::GetParent(pNode) | 
 |                                      : nullptr; | 
 |   } | 
 |  | 
 |   NodeType* NextSiblingWithinSubtree(NodeType* pNode) { | 
 |     return pNode != m_pRoot ? TraverseStrategy::GetNextSibling(pNode) : nullptr; | 
 |   } | 
 |  | 
 |   NodeType* PreviousSiblingWithinSubtree(NodeType* pNode) { | 
 |     NodeType* pParent = ParentWithinSubtree(pNode); | 
 |     if (!pParent) | 
 |       return nullptr; | 
 |     NodeType* pCurrent = TraverseStrategy::GetFirstChild(pParent); | 
 |     NodeType* pPrevious = nullptr; | 
 |     while (pCurrent != pNode) { | 
 |       pPrevious = pCurrent; | 
 |       pCurrent = TraverseStrategy::GetNextSibling(pCurrent); | 
 |     } | 
 |     return pPrevious; | 
 |   } | 
 |  | 
 |   NodeType* LastChild(NodeType* pNode) { | 
 |     NodeType* pPrevious = nullptr; | 
 |     NodeType* pChild = TraverseStrategy::GetFirstChild(pNode); | 
 |     while (pChild) { | 
 |       pPrevious = pChild; | 
 |       pChild = NextSiblingWithinSubtree(pChild); | 
 |     } | 
 |     return pPrevious; | 
 |   } | 
 |  | 
 |   NodeType* LastDescendant(NodeType* pNode) { | 
 |     NodeType* pChild = LastChild(pNode); | 
 |     return pChild ? LastDescendant(pChild) : pNode; | 
 |   } | 
 |  | 
 |   HolderType m_pRoot; | 
 |   HolderType m_pCurrent; | 
 | }; | 
 |  | 
 | #endif  // XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_ |