| 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 30 matching lines...) Expand all Loading... |
| 41 // | 41 // |
| 42 // * Each TreeNode node is NOT ref counted. The user have to retain its lifetim
e somehow. | 42 // * Each TreeNode node is NOT ref counted. The user have to retain its lifetim
e somehow. |
| 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 // FIXME: oilpan: Trace tree node edges to ensure we don't have dangling pointer
s. | 47 // FIXME: oilpan: Trace tree node edges to ensure we don't have dangling pointer
s. |
| 48 // As it is used in HTMLImport it is safe since they all die together. | 48 // As it is used in HTMLImport it is safe since they all die together. |
| 49 template <class T> | 49 template <class T> |
| 50 class TreeNode { | 50 class TreeNode { |
| 51 public: | 51 public: |
| 52 typedef T NodeType; | 52 typedef T NodeType; |
| 53 | 53 |
| 54 TreeNode() | 54 TreeNode() |
| 55 : m_next(0) | 55 : m_next(0), |
| 56 , m_previous(0) | 56 m_previous(0), |
| 57 , m_parent(0) | 57 m_parent(0), |
| 58 , m_firstChild(0) | 58 m_firstChild(0), |
| 59 , m_lastChild(0) | 59 m_lastChild(0) {} |
| 60 { | 60 |
| 61 NodeType* next() const { return m_next; } |
| 62 NodeType* previous() const { return m_previous; } |
| 63 NodeType* parent() const { return m_parent; } |
| 64 NodeType* firstChild() const { return m_firstChild; } |
| 65 NodeType* lastChild() const { return m_lastChild; } |
| 66 NodeType* here() const { |
| 67 return static_cast<NodeType*>(const_cast<TreeNode*>(this)); |
| 68 } |
| 69 |
| 70 bool orphan() const { |
| 71 return !m_parent && !m_next && !m_previous && !m_firstChild && !m_lastChild; |
| 72 } |
| 73 bool hasChildren() const { return m_firstChild; } |
| 74 |
| 75 void insertBefore(NodeType* newChild, NodeType* refChild) { |
| 76 ASSERT(!newChild->parent()); |
| 77 ASSERT(!newChild->next()); |
| 78 ASSERT(!newChild->previous()); |
| 79 |
| 80 ASSERT(!refChild || this == refChild->parent()); |
| 81 |
| 82 if (!refChild) { |
| 83 appendChild(newChild); |
| 84 return; |
| 61 } | 85 } |
| 62 | 86 |
| 63 NodeType* next() const { return m_next; } | 87 NodeType* newPrevious = refChild->previous(); |
| 64 NodeType* previous() const { return m_previous; } | 88 newChild->m_parent = here(); |
| 65 NodeType* parent() const { return m_parent; } | 89 newChild->m_next = refChild; |
| 66 NodeType* firstChild() const { return m_firstChild; } | 90 newChild->m_previous = newPrevious; |
| 67 NodeType* lastChild() const { return m_lastChild; } | 91 refChild->m_previous = newChild; |
| 68 NodeType* here() const { return static_cast<NodeType*>(const_cast<TreeNode*>
(this)); } | 92 if (newPrevious) |
| 93 newPrevious->m_next = newChild; |
| 94 else |
| 95 m_firstChild = newChild; |
| 96 } |
| 69 | 97 |
| 70 bool orphan() const { return !m_parent && !m_next && !m_previous && !m_first
Child && !m_lastChild; } | 98 void appendChild(NodeType* child) { |
| 71 bool hasChildren() const { return m_firstChild; } | 99 ASSERT(!child->parent()); |
| 100 ASSERT(!child->next()); |
| 101 ASSERT(!child->previous()); |
| 72 | 102 |
| 73 void insertBefore(NodeType* newChild, NodeType* refChild) | 103 child->m_parent = here(); |
| 74 { | |
| 75 ASSERT(!newChild->parent()); | |
| 76 ASSERT(!newChild->next()); | |
| 77 ASSERT(!newChild->previous()); | |
| 78 | 104 |
| 79 ASSERT(!refChild || this == refChild->parent()); | 105 if (!m_lastChild) { |
| 80 | 106 ASSERT(!m_firstChild); |
| 81 if (!refChild) { | 107 m_lastChild = m_firstChild = child; |
| 82 appendChild(newChild); | 108 return; |
| 83 return; | |
| 84 } | |
| 85 | |
| 86 NodeType* newPrevious = refChild->previous(); | |
| 87 newChild->m_parent = here(); | |
| 88 newChild->m_next = refChild; | |
| 89 newChild->m_previous = newPrevious; | |
| 90 refChild->m_previous = newChild; | |
| 91 if (newPrevious) | |
| 92 newPrevious->m_next = newChild; | |
| 93 else | |
| 94 m_firstChild = newChild; | |
| 95 } | 109 } |
| 96 | 110 |
| 97 void appendChild(NodeType* child) | 111 ASSERT(!m_lastChild->m_next); |
| 98 { | 112 NodeType* oldLast = m_lastChild; |
| 99 ASSERT(!child->parent()); | 113 m_lastChild = child; |
| 100 ASSERT(!child->next()); | |
| 101 ASSERT(!child->previous()); | |
| 102 | 114 |
| 103 child->m_parent = here(); | 115 child->m_previous = oldLast; |
| 116 oldLast->m_next = child; |
| 117 } |
| 104 | 118 |
| 105 if (!m_lastChild) { | 119 NodeType* removeChild(NodeType* child) { |
| 106 ASSERT(!m_firstChild); | 120 ASSERT(child->parent() == this); |
| 107 m_lastChild = m_firstChild = child; | |
| 108 return; | |
| 109 } | |
| 110 | 121 |
| 111 ASSERT(!m_lastChild->m_next); | 122 if (m_firstChild == child) |
| 112 NodeType* oldLast = m_lastChild; | 123 m_firstChild = child->next(); |
| 113 m_lastChild = child; | 124 if (m_lastChild == child) |
| 125 m_lastChild = child->previous(); |
| 114 | 126 |
| 115 child->m_previous = oldLast; | 127 NodeType* oldNext = child->next(); |
| 116 oldLast->m_next = child; | 128 NodeType* oldPrevious = child->previous(); |
| 129 child->m_parent = child->m_next = child->m_previous = 0; |
| 130 |
| 131 if (oldNext) |
| 132 oldNext->m_previous = oldPrevious; |
| 133 if (oldPrevious) |
| 134 oldPrevious->m_next = oldNext; |
| 135 |
| 136 return child; |
| 137 } |
| 138 |
| 139 void takeChildrenFrom(NodeType* oldParent) { |
| 140 ASSERT(oldParent != this); |
| 141 while (oldParent->hasChildren()) { |
| 142 NodeType* child = oldParent->firstChild(); |
| 143 oldParent->removeChild(child); |
| 144 this->appendChild(child); |
| 117 } | 145 } |
| 146 } |
| 118 | 147 |
| 119 NodeType* removeChild(NodeType* child) | 148 private: |
| 120 { | 149 NodeType* m_next; |
| 121 ASSERT(child->parent() == this); | 150 NodeType* m_previous; |
| 122 | 151 NodeType* m_parent; |
| 123 if (m_firstChild == child) | 152 NodeType* m_firstChild; |
| 124 m_firstChild = child->next(); | 153 NodeType* m_lastChild; |
| 125 if (m_lastChild == child) | |
| 126 m_lastChild = child->previous(); | |
| 127 | |
| 128 NodeType* oldNext = child->next(); | |
| 129 NodeType* oldPrevious = child->previous(); | |
| 130 child->m_parent = child->m_next = child->m_previous = 0; | |
| 131 | |
| 132 if (oldNext) | |
| 133 oldNext->m_previous = oldPrevious; | |
| 134 if (oldPrevious) | |
| 135 oldPrevious->m_next = oldNext; | |
| 136 | |
| 137 return child; | |
| 138 } | |
| 139 | |
| 140 void takeChildrenFrom(NodeType* oldParent) | |
| 141 { | |
| 142 ASSERT(oldParent != this); | |
| 143 while (oldParent->hasChildren()) { | |
| 144 NodeType* child = oldParent->firstChild(); | |
| 145 oldParent->removeChild(child); | |
| 146 this->appendChild(child); | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 private: | |
| 151 NodeType* m_next; | |
| 152 NodeType* m_previous; | |
| 153 NodeType* m_parent; | |
| 154 NodeType* m_firstChild; | |
| 155 NodeType* m_lastChild; | |
| 156 }; | 154 }; |
| 157 | 155 |
| 158 template<class T> | 156 template <class T> |
| 159 inline typename TreeNode<T>::NodeType* traverseNext(const TreeNode<T>* current,
const TreeNode<T>* stayWithin = 0) | 157 inline typename TreeNode<T>::NodeType* traverseNext( |
| 160 { | 158 const TreeNode<T>* current, |
| 161 if (typename TreeNode<T>::NodeType* next = current->firstChild()) | 159 const TreeNode<T>* stayWithin = 0) { |
| 162 return next; | 160 if (typename TreeNode<T>::NodeType* next = current->firstChild()) |
| 163 if (current == stayWithin) | 161 return next; |
| 164 return 0; | 162 if (current == stayWithin) |
| 165 if (typename TreeNode<T>::NodeType* next = current->next()) | 163 return 0; |
| 166 return next; | 164 if (typename TreeNode<T>::NodeType* next = current->next()) |
| 167 for (typename TreeNode<T>::NodeType* parent = current->parent(); parent; par
ent = parent->parent()) { | 165 return next; |
| 168 if (parent == stayWithin) | 166 for (typename TreeNode<T>::NodeType* parent = current->parent(); parent; |
| 169 return 0; | 167 parent = parent->parent()) { |
| 170 if (typename TreeNode<T>::NodeType* next = parent->next()) | 168 if (parent == stayWithin) |
| 171 return next; | 169 return 0; |
| 172 } | 170 if (typename TreeNode<T>::NodeType* next = parent->next()) |
| 171 return next; |
| 172 } |
| 173 | 173 |
| 174 return 0; | 174 return 0; |
| 175 } | 175 } |
| 176 | 176 |
| 177 template<class T> | 177 template <class T> |
| 178 inline typename TreeNode<T>::NodeType* traverseFirstPostOrder(const TreeNode<T>*
current) | 178 inline typename TreeNode<T>::NodeType* traverseFirstPostOrder( |
| 179 { | 179 const TreeNode<T>* current) { |
| 180 typename TreeNode<T>::NodeType* first = current->here(); | 180 typename TreeNode<T>::NodeType* first = current->here(); |
| 181 while (first->firstChild()) | 181 while (first->firstChild()) |
| 182 first = first->firstChild(); | 182 first = first->firstChild(); |
| 183 return first; | 183 return first; |
| 184 } | 184 } |
| 185 | 185 |
| 186 template<class T> | 186 template <class T> |
| 187 inline typename TreeNode<T>::NodeType* traverseNextPostOrder(const TreeNode<T>*
current, const TreeNode<T>* stayWithin = 0) | 187 inline typename TreeNode<T>::NodeType* traverseNextPostOrder( |
| 188 { | 188 const TreeNode<T>* current, |
| 189 if (current == stayWithin) | 189 const TreeNode<T>* stayWithin = 0) { |
| 190 return 0; | 190 if (current == stayWithin) |
| 191 return 0; |
| 191 | 192 |
| 192 typename TreeNode<T>::NodeType* next = current->next(); | 193 typename TreeNode<T>::NodeType* next = current->next(); |
| 193 if (!next) | 194 if (!next) |
| 194 return current->parent(); | 195 return current->parent(); |
| 195 while (next->firstChild()) | 196 while (next->firstChild()) |
| 196 next = next->firstChild(); | 197 next = next->firstChild(); |
| 197 return next; | 198 return next; |
| 198 } | 199 } |
| 199 | |
| 200 } | 200 } |
| 201 | 201 |
| 202 using WTF::TreeNode; | 202 using WTF::TreeNode; |
| 203 using WTF::traverseNext; | 203 using WTF::traverseNext; |
| 204 using WTF::traverseNextPostOrder; | 204 using WTF::traverseNextPostOrder; |
| 205 | 205 |
| 206 #endif | 206 #endif |
| OLD | NEW |