OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 // FIXME: lifetime management could be parameterized so that ref counted impl ementations can be used. | 43 // FIXME: lifetime management could be parameterized so that ref counted impl ementations can be used. |
44 // * It ASSERT()s invalid input. The callers have to ensure that given paramete r is sound. | 44 // * It ASSERT()s invalid input. The callers have to ensure that given paramete r is sound. |
45 // * There is no branch-leaf difference. Every node can be a parent of other no de. | 45 // * There is no branch-leaf difference. Every node can be a parent of other no de. |
46 // | 46 // |
47 template <class T> | 47 template <class T> |
48 class TreeNode { | 48 class TreeNode { |
49 public: | 49 public: |
50 typedef T NodeType; | 50 typedef T NodeType; |
51 | 51 |
52 TreeNode() | 52 TreeNode() |
53 : m_next(0) | 53 : m_nextSibling(0) |
54 , m_previous(0) | 54 , m_previousSibling(0) |
55 , m_parent(0) | 55 , m_parent(0) |
56 , m_firstChild(0) | 56 , m_firstChild(0) |
57 , m_lastChild(0) | 57 , m_lastChild(0) |
58 { | 58 { |
59 } | 59 } |
60 | 60 |
61 NodeType* next() const { return m_next; } | 61 NodeType* nextSibling() const { return m_nextSibling; } |
62 NodeType* previous() const { return m_previous; } | 62 NodeType* previousSibling() const { return m_previousSibling; } |
63 NodeType* parent() const { return m_parent; } | 63 NodeType* parent() const { return m_parent; } |
64 NodeType* firstChild() const { return m_firstChild; } | 64 NodeType* firstChild() const { return m_firstChild; } |
65 NodeType* lastChild() const { return m_lastChild; } | 65 NodeType* lastChild() const { return m_lastChild; } |
66 NodeType* here() const { return static_cast<NodeType*>(const_cast<TreeNode*> (this)); } | 66 NodeType* here() const { return static_cast<NodeType*>(const_cast<TreeNode*> (this)); } |
67 | 67 |
68 bool orphan() const { return !m_parent && !m_next && !m_previous && !m_first Child && !m_lastChild; } | 68 bool orphan() const { return !m_parent && !m_nextSibling && !m_previousSibli ng && !m_firstChild && !m_lastChild; } |
69 bool hasChildren() const { return m_firstChild; } | 69 bool hasChildren() const { return m_firstChild; } |
70 | 70 |
71 void insertBefore(NodeType* newChild, NodeType* refChild) | 71 void insertBefore(NodeType* newChild, NodeType* refChild) |
72 { | 72 { |
73 ASSERT(!newChild->parent()); | 73 ASSERT(!newChild->parent()); |
74 ASSERT(!newChild->next()); | 74 ASSERT(!newChild->nextSibling()); |
75 ASSERT(!newChild->previous()); | 75 ASSERT(!newChild->previousSibling()); |
76 | 76 |
77 ASSERT(!refChild || this == refChild->parent()); | 77 ASSERT(!refChild || this == refChild->parent()); |
78 | 78 |
79 if (!refChild) { | 79 if (!refChild) { |
80 appendChild(newChild); | 80 appendChild(newChild); |
81 return; | 81 return; |
82 } | 82 } |
83 | 83 |
84 NodeType* newPrevious = refChild->previous(); | 84 NodeType* newPrevious = refChild->previousSibling(); |
85 newChild->m_parent = here(); | 85 newChild->m_parent = here(); |
86 newChild->m_next = refChild; | 86 newChild->m_nextSibling = refChild; |
87 newChild->m_previous = newPrevious; | 87 newChild->m_previousSibling = newPrevious; |
88 refChild->m_previous = newChild; | 88 refChild->m_previousSibling = newChild; |
89 if (newPrevious) | 89 if (newPrevious) |
90 newPrevious->m_next = newChild; | 90 newPrevious->m_nextSibling = newChild; |
91 else | 91 else |
92 m_firstChild = newChild; | 92 m_firstChild = newChild; |
93 } | 93 } |
94 | 94 |
95 void appendChild(NodeType* child) | 95 void appendChild(NodeType* child) |
96 { | 96 { |
97 ASSERT(!child->parent()); | 97 ASSERT(!child->parent()); |
98 ASSERT(!child->next()); | 98 ASSERT(!child->nextSibling()); |
99 ASSERT(!child->previous()); | 99 ASSERT(!child->previousSibling()); |
100 | 100 |
101 child->m_parent = here(); | 101 child->m_parent = here(); |
102 | 102 |
103 if (!m_lastChild) { | 103 if (!m_lastChild) { |
104 ASSERT(!m_firstChild); | 104 ASSERT(!m_firstChild); |
105 m_lastChild = m_firstChild = child; | 105 m_lastChild = m_firstChild = child; |
106 return; | 106 return; |
107 } | 107 } |
108 | 108 |
109 ASSERT(!m_lastChild->m_next); | 109 ASSERT(!m_lastChild->m_nextSibling); |
110 NodeType* oldLast = m_lastChild; | 110 NodeType* oldLast = m_lastChild; |
111 m_lastChild = child; | 111 m_lastChild = child; |
112 | 112 |
113 child->m_previous = oldLast; | 113 child->m_previousSibling = oldLast; |
114 oldLast->m_next = child; | 114 oldLast->m_nextSibling = child; |
115 } | 115 } |
116 | 116 |
117 NodeType* removeChild(NodeType* child) | 117 NodeType* removeChild(NodeType* child) |
118 { | 118 { |
119 ASSERT(child->parent() == this); | 119 ASSERT(child->parent() == this); |
120 | 120 |
121 if (m_firstChild == child) | 121 if (m_firstChild == child) |
122 m_firstChild = child->next(); | 122 m_firstChild = child->nextSibling(); |
123 if (m_lastChild == child) | 123 if (m_lastChild == child) |
124 m_lastChild = child->previous(); | 124 m_lastChild = child->previousSibling(); |
125 | 125 |
126 NodeType* oldNext = child->next(); | 126 NodeType* oldNext = child->nextSibling(); |
127 NodeType* oldPrevious = child->previous(); | 127 NodeType* oldPrevious = child->previousSibling(); |
128 child->m_parent = child->m_next = child->m_previous = 0; | 128 child->m_parent = child->m_nextSibling = child->m_previousSibling = 0; |
129 | 129 |
130 if (oldNext) | 130 if (oldNext) |
131 oldNext->m_previous = oldPrevious; | 131 oldNext->m_previousSibling = oldPrevious; |
132 if (oldPrevious) | 132 if (oldPrevious) |
133 oldPrevious->m_next = oldNext; | 133 oldPrevious->m_nextSibling = oldNext; |
134 | 134 |
135 return child; | 135 return child; |
136 } | 136 } |
137 | 137 |
138 private: | 138 private: |
139 NodeType* m_next; | 139 NodeType* m_nextSibling; |
140 NodeType* m_previous; | 140 NodeType* m_previousSibling; |
141 NodeType* m_parent; | 141 NodeType* m_parent; |
142 NodeType* m_firstChild; | 142 NodeType* m_firstChild; |
143 NodeType* m_lastChild; | 143 NodeType* m_lastChild; |
144 }; | 144 }; |
145 | 145 |
146 template<class T> | 146 /* non-recursive pre-order traversal */ |
147 inline typename TreeNode<T>::NodeType* traverseNext(const TreeNode<T>* current, const TreeNode<T>* stayWithin = 0) | 147 template<class NodeType, class ContainerType> |
Inactive
2014/01/08 03:08:01
BTW, I am not a big fan of the NodeType / Containe
| |
148 inline NodeType* traverseNext(const ContainerType& current) | |
148 { | 149 { |
149 if (typename TreeNode<T>::NodeType* next = current->firstChild()) | 150 if (NodeType* firstChild = current.firstChild()) |
150 return next; | 151 return firstChild; |
151 if (current == stayWithin) | 152 if (NodeType* nextSibling = current.nextSibling()) |
152 return 0; | 153 return nextSibling; |
153 if (typename TreeNode<T>::NodeType* next = current->next()) | 154 for (NodeType* parent = current.parent(); parent; parent = parent->parent()) { |
154 return next; | 155 if (NodeType* nextSibling = parent->nextSibling()) |
155 for (typename TreeNode<T>::NodeType* parent = current->parent(); parent; par ent = parent->parent()) { | 156 return nextSibling; |
156 if (parent == stayWithin) | |
157 return 0; | |
158 if (typename TreeNode<T>::NodeType* next = parent->next()) | |
159 return next; | |
160 } | 157 } |
161 | 158 |
162 return 0; | 159 return 0; |
163 } | 160 } |
164 | 161 |
165 template<class T> | 162 template<class ContainerType> |
166 inline typename TreeNode<T>::NodeType* traverseFirstPostOrder(const TreeNode<T>* current) | 163 inline ContainerType* traverseNext(const ContainerType& current) |
164 { return traverseNext<ContainerType, ContainerType>(current); } | |
165 | |
166 template<class NodeType, class ContainerType> | |
167 inline NodeType* traverseNext(const ContainerType& current, const NodeType* stay Within) | |
167 { | 168 { |
168 typename TreeNode<T>::NodeType* first = current->here(); | 169 if (NodeType* firstChild = current.firstChild()) |
170 return firstChild; | |
171 if (¤t == stayWithin) | |
172 return 0; | |
173 if (NodeType* nextSibling = current.nextSibling()) | |
174 return nextSibling; | |
175 for (NodeType* parent = current.parent(); parent; parent = parent->parent()) { | |
176 if (parent == stayWithin) | |
177 return 0; | |
178 if (NodeType* nextSibling = parent->nextSibling()) | |
179 return nextSibling; | |
180 } | |
181 | |
182 return 0; | |
183 } | |
184 | |
185 template<class ContainerType> | |
186 inline ContainerType* traverseNext(const ContainerType& current, const Container Type* stayWithin) | |
187 { return traverseNext<ContainerType, ContainerType>(current, stayWithin); } | |
188 | |
189 /* non-recursive post-order traversal */ | |
190 template<class NodeType, class ContainerType> | |
191 inline NodeType* traverseFirstPostOrder(const ContainerType& current) | |
192 { | |
193 NodeType* first = current.here(); | |
169 while (first->firstChild()) | 194 while (first->firstChild()) |
170 first = first->firstChild(); | 195 first = first->firstChild(); |
171 return first; | 196 return first; |
172 } | 197 } |
173 | 198 |
174 template<class T> | 199 template<class ContainerType> |
175 inline typename TreeNode<T>::NodeType* traverseNextPostOrder(const TreeNode<T>* current, const TreeNode<T>* stayWithin = 0) | 200 inline ContainerType* traverseFirstPostOrder(const ContainerType& current) |
201 { return traverseFirstPostOrder<ContainerType, ContainerType>(current); } | |
202 | |
203 template<class NodeType, class ContainerType> | |
204 inline NodeType* traverseNextPostOrder(const ContainerType& current) | |
205 { | |
206 NodeType* nextSibling = current.nextSibling(); | |
207 if (!nextSibling) | |
208 return current.parent(); | |
209 while (nextSibling->firstChild()) | |
210 nextSibling = nextSibling->firstChild(); | |
211 return nextSibling; | |
212 } | |
213 | |
214 template<class ContainerType> | |
215 inline ContainerType* traverseNextPostOrder(const ContainerType& current) | |
216 { return traverseNextPostOrder<ContainerType, ContainerType>(current); } | |
217 | |
218 template<class NodeType, class ContainerType> | |
219 inline NodeType* traverseNextPostOrder(const ContainerType& current, const NodeT ype* stayWithin) | |
220 { | |
221 if (¤t == stayWithin) | |
222 return 0; | |
223 | |
224 NodeType* nextSibling = current.nextSibling(); | |
225 if (!nextSibling) | |
226 return current.parent(); | |
227 while (nextSibling->firstChild()) | |
228 nextSibling = nextSibling->firstChild(); | |
229 return nextSibling; | |
230 } | |
231 | |
232 template<class ContainerType> | |
233 inline ContainerType* traverseNextPostOrder(const ContainerType& current, const ContainerType* stayWithin) | |
234 { return traverseNextPostOrder<ContainerType, ContainerType>(current, stayWithin ); } | |
235 | |
236 /* non-recursive traversal skipping children */ | |
237 template <class NodeType, class ContainerType> | |
238 inline NodeType* traverseNextSkippingChildren(const ContainerType& current) | |
239 { | |
240 if (current.nextSibling()) | |
241 return current.nextSibling(); | |
242 for (NodeType* parent = current.parent(); parent; parent = parent->parent()) { | |
243 if (NodeType* nextSibling = parent->nextSibling()) | |
244 return nextSibling; | |
245 } | |
246 | |
247 return 0; | |
248 } | |
249 | |
250 template <class ContainerType> | |
251 inline ContainerType* traverseNextSkippingChildren(const ContainerType& current) | |
252 { return traverseNextSkippingChildren<ContainerType, ContainerType>(current); } | |
253 | |
254 template <class NodeType, class ContainerType> | |
255 inline NodeType* traverseNextSkippingChildren(const ContainerType& current, cons t NodeType* stayWithin) | |
176 { | 256 { |
177 if (current == stayWithin) | 257 if (current == stayWithin) |
178 return 0; | 258 return 0; |
259 if (current.nextSibling()) | |
260 return current.nextSibling(); | |
261 for (NodeType* parent = current.parent(); parent; parent = parent->parent()) { | |
262 if (parent == stayWithin) | |
263 return 0; | |
264 if (NodeType* nextSibling = parent->nextSibling()) | |
265 return nextSibling; | |
266 } | |
179 | 267 |
180 typename TreeNode<T>::NodeType* next = current->next(); | 268 return 0; |
181 if (!next) | |
182 return current->parent(); | |
183 while (next->firstChild()) | |
184 next = next->firstChild(); | |
185 return next; | |
186 } | 269 } |
187 | 270 |
188 } | 271 template <class ContainerType> |
272 inline ContainerType* traverseNextSkippingChildren(const ContainerType& current, const ContainerType* stayWithin) | |
273 { return traverseNextSkippingChildren<ContainerType, ContainerType>(current, sta yWithin); } | |
274 | |
275 } // namespace WTF | |
189 | 276 |
190 using WTF::TreeNode; | 277 using WTF::TreeNode; |
191 using WTF::traverseNext; | 278 using WTF::traverseNext; |
279 using WTF::traverseFirstPostOrder; | |
192 using WTF::traverseNextPostOrder; | 280 using WTF::traverseNextPostOrder; |
281 using WTF::traverseNextSkippingChildren; | |
193 | 282 |
194 #endif | 283 #endif // TreeNode_h |
OLD | NEW |