Chromium Code Reviews| 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 |