blob: 214f38e50129067f294087f1f5935b313dd7e045 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// 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_
template <class NodeType, class TraverseStrategy>
class CXFA_NodeIteratorTemplate {
public:
explicit CXFA_NodeIteratorTemplate(NodeType* pRoot)
: m_pRoot(pRoot), m_pCurrent(pRoot) {}
NodeType* GetRoot() const { return m_pRoot; }
NodeType* GetCurrent() const { return 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(m_pRoot);
return m_pCurrent;
}
NodeType* pSibling = PreviousSiblingWithinSubtree(m_pCurrent);
if (pSibling) {
m_pCurrent = LastDescendant(pSibling);
return m_pCurrent;
}
NodeType* pParent = ParentWithinSubtree(m_pCurrent);
if (pParent) {
m_pCurrent = pParent;
return m_pCurrent;
}
return nullptr;
}
NodeType* MoveToNext() {
if (!m_pRoot || !m_pCurrent)
return nullptr;
NodeType* pChild = TraverseStrategy::GetFirstChild(m_pCurrent);
if (pChild) {
m_pCurrent = pChild;
return m_pCurrent;
}
return SkipChildrenAndMoveToNext();
}
NodeType* SkipChildrenAndMoveToNext() {
if (!m_pRoot)
return nullptr;
NodeType* pNode = m_pCurrent;
while (pNode) {
NodeType* pSibling = NextSiblingWithinSubtree(pNode);
if (pSibling) {
m_pCurrent = pSibling;
return m_pCurrent;
}
pNode = ParentWithinSubtree(pNode);
}
m_pCurrent = nullptr;
return m_pCurrent;
}
private:
bool RootReachableFromNode(NodeType* pNode) {
if (!pNode)
return false;
if (pNode == m_pRoot)
return true;
return RootReachableFromNode(TraverseStrategy::GetParent(pNode));
}
NodeType* ParentWithinSubtree(NodeType* pNode) {
if (!pNode || pNode == m_pRoot)
return nullptr;
return TraverseStrategy::GetParent(pNode);
}
NodeType* NextSiblingWithinSubtree(NodeType* pNode) {
if (pNode == m_pRoot)
return nullptr;
return TraverseStrategy::GetNextSibling(pNode);
}
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;
}
NodeType* m_pRoot;
NodeType* m_pCurrent;
};
#endif // XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_
|