OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkTInternalLList_DEFINED | 8 #ifndef SkTInternalLList_DEFINED |
9 #define SkTInternalLList_DEFINED | 9 #define SkTInternalLList_DEFINED |
10 | 10 |
(...skipping 11 matching lines...) Expand all Loading... | |
22 private: | 22 private: |
23 T* fPtr; | 23 T* fPtr; |
24 }; | 24 }; |
25 | 25 |
26 | 26 |
27 /** | 27 /** |
28 * This macro creates the member variables required by the SkTInternalLList clas s. It should be | 28 * This macro creates the member variables required by the SkTInternalLList clas s. It should be |
29 * placed in the private section of any class that will be stored in a double li nked list. | 29 * placed in the private section of any class that will be stored in a double li nked list. |
30 */ | 30 */ |
31 #define SK_DECLARE_INTERNAL_LLIST_INTERFACE(ClassName) \ | 31 #define SK_DECLARE_INTERNAL_LLIST_INTERFACE(ClassName) \ |
32 friend class SkTInternalLList<ClassName>; \ | 32 friend class SkTInternalLListDefaultExtractor<ClassName>; \ |
mtklein
2013/12/03 19:02:02
I'm somewhat worried about the general design of G
| |
33 /* back pointer to the owning list - for debugging */ \ | 33 /* back pointer to the owning list - for debugging */ \ |
34 SkDEBUGCODE(SkPtrWrapper<SkTInternalLList<ClassName> > fList;) \ | 34 SkDEBUGCODE(SkPtrWrapper<SkTInternalLList<ClassName> > fList;) \ |
35 SkPtrWrapper<ClassName> fPrev; \ | 35 SkPtrWrapper<ClassName> fPrev; \ |
36 SkPtrWrapper<ClassName> fNext | 36 SkPtrWrapper<ClassName> fNext; |
37 | |
38 /** | |
39 * This macro creates the members for storing the instance to a specific, named linked list. It | |
40 * should be placed in the public section of any class that will be stored in a double linked | |
41 * list. Classes that use this macro need to use corresponding _DATA macro below . | |
42 */ | |
43 #define SK_DECLARE_NAMED_INTERNAL_LLIST_INTERFACE(T, Name) \ | |
44 struct InternalLListExtractor##Name { \ | |
45 typedef SkTInternalLList<T, InternalLListExtractor##Name > ListType; \ | |
46 static SkPtrWrapper<T>& Prev(T* o) { return o->fPrev##Name; } \ | |
47 static SkPtrWrapper<T>& Next(T* o) { return o->fNext##Name; } \ | |
48 SkDEBUGCODE(static SkPtrWrapper<ListType>& List(T* o) { return o->fList# #Name; }) \ | |
49 SkDEBUGCODE(static const ListType* List(const T* o) { return o->fList##N ame; }) \ | |
50 }; \ | |
51 friend class InternalLListExtractor##Name; | |
52 | |
53 /** | |
54 * This macro creates the member variables for storing the instance to a specifi c, named linked | |
55 * list. It should be placed in the private section of the class. | |
56 */ | |
57 #define SK_DECLARE_NAMED_INTERNAL_LLIST_INTERFACE_DATA(T, Name) \ | |
58 SkPtrWrapper<T> fPrev##Name; \ | |
59 SkPtrWrapper<T> fNext##Name; \ | |
60 SkDEBUGCODE(SkPtrWrapper<InternalLListExtractor##Name::ListType> fList##Name ;) | |
61 | |
62 /** | |
63 * This macro creates the member variable and short-cut typedefs for a specific, named linked list. | |
64 * This should be placed in the class declaration or code that creates the named linked list. | |
65 */ | |
66 #define SK_DECLARE_NAMED_INTERNAL_LLIST(T, Name, VarName) \ | |
67 typedef SkTInternalLList<T, T::InternalLListExtractor##Name> Name##InternalL ListType; \ | |
68 Name##InternalLListType VarName; | |
69 | |
70 template <class T, class E> class SkTInternalLList; | |
71 | |
72 template<typename T> | |
73 struct SkTInternalLListDefaultExtractor { | |
74 typedef SkTInternalLList<T, SkTInternalLListDefaultExtractor<T> > ListType; | |
75 static SkPtrWrapper<T>& Prev(T* o) { return o->fPrev; } | |
76 static SkPtrWrapper<T>& Next(T* o) { return o->fNext; } | |
77 SkDEBUGCODE(static SkPtrWrapper<ListType>& List(T* o) { return o->fList; }) | |
78 SkDEBUGCODE(static const ListType* List(const T* o) { return o->fList; }) | |
79 }; | |
37 | 80 |
38 /** | 81 /** |
39 * This class implements a templated internal doubly linked list data structure. | 82 * This class implements a templated internal doubly linked list data structure. |
40 */ | 83 */ |
41 template <class T> class SkTInternalLList : public SkNoncopyable { | 84 template <class T, class E = SkTInternalLListDefaultExtractor<T> > |
85 class SkTInternalLList : public SkNoncopyable { | |
42 public: | 86 public: |
43 SkTInternalLList() | 87 SkTInternalLList() |
44 : fHead(NULL) | 88 : fHead(NULL) |
45 , fTail(NULL) { | 89 , fTail(NULL) { |
46 } | 90 } |
47 | 91 |
48 void remove(T* entry) { | 92 void remove(T* entry) { |
49 SkASSERT(NULL != fHead && NULL != fTail); | 93 SkASSERT(NULL != fHead && NULL != fTail); |
50 SkASSERT(this->isInList(entry)); | 94 SkASSERT(this->isInList(entry)); |
51 | 95 |
52 T* prev = entry->fPrev; | 96 T* prev = E::Prev(entry); |
53 T* next = entry->fNext; | 97 T* next = E::Next(entry); |
54 | 98 |
55 if (NULL != prev) { | 99 if (NULL != prev) { |
56 prev->fNext = next; | 100 E::Next(prev) = next; |
57 } else { | 101 } else { |
58 fHead = next; | 102 fHead = next; |
59 } | 103 } |
60 if (NULL != next) { | 104 if (NULL != next) { |
61 next->fPrev = prev; | 105 E::Prev(next) = prev; |
62 } else { | 106 } else { |
63 fTail = prev; | 107 fTail = prev; |
64 } | 108 } |
65 | 109 |
66 entry->fPrev = NULL; | 110 E::Prev(entry) = NULL; |
67 entry->fNext = NULL; | 111 E::Next(entry) = NULL; |
68 | 112 |
69 #ifdef SK_DEBUG | 113 #ifdef SK_DEBUG |
70 entry->fList = NULL; | 114 E::List(entry) = NULL; |
71 #endif | 115 #endif |
72 } | 116 } |
73 | 117 |
74 void addToHead(T* entry) { | 118 void addToHead(T* entry) { |
75 SkASSERT(NULL == entry->fPrev && NULL == entry->fNext); | 119 SkASSERT(NULL == E::Prev(entry) && NULL == E::Next(entry)); |
76 SkASSERT(NULL == entry->fList); | 120 SkASSERT(NULL == E::List(entry)); |
77 | 121 |
78 entry->fPrev = NULL; | 122 E::Prev(entry) = NULL; |
79 entry->fNext = fHead; | 123 E::Next(entry) = fHead; |
80 if (NULL != fHead) { | 124 if (NULL != fHead) { |
81 fHead->fPrev = entry; | 125 E::Prev(fHead) = entry; |
82 } | 126 } |
83 fHead = entry; | 127 fHead = entry; |
84 if (NULL == fTail) { | 128 if (NULL == fTail) { |
85 fTail = entry; | 129 fTail = entry; |
86 } | 130 } |
87 | 131 |
88 #ifdef SK_DEBUG | 132 #ifdef SK_DEBUG |
89 entry->fList = this; | 133 E::List(entry) = this; |
90 #endif | 134 #endif |
91 } | 135 } |
92 | 136 |
93 void addToTail(T* entry) { | 137 void addToTail(T* entry) { |
94 SkASSERT(NULL == entry->fPrev && NULL == entry->fNext); | 138 SkASSERT(NULL == E::Prev(entry) && NULL == E::Next(entry)); |
95 SkASSERT(NULL == entry->fList); | 139 SkASSERT(NULL == E::List(entry)); |
96 | 140 |
97 entry->fPrev = fTail; | 141 E::Prev(entry) = fTail; |
98 entry->fNext = NULL; | 142 E::Next(entry) = NULL; |
99 if (NULL != fTail) { | 143 if (NULL != fTail) { |
100 fTail->fNext = entry; | 144 E::Next(fTail) = entry; |
101 } | 145 } |
102 fTail = entry; | 146 fTail = entry; |
103 if (NULL == fHead) { | 147 if (NULL == fHead) { |
104 fHead = entry; | 148 fHead = entry; |
105 } | 149 } |
106 | 150 |
107 #ifdef SK_DEBUG | 151 #ifdef SK_DEBUG |
108 entry->fList = this; | 152 E::List(entry) = this; |
109 #endif | 153 #endif |
110 } | 154 } |
111 | 155 |
112 /** | 156 /** |
113 * Inserts a new list entry before an existing list entry. The new entry mus t not already be | 157 * Inserts a new list entry before an existing list entry. The new entry mus t not already be |
114 * a member of this or any other list. If existingEntry is NULL then the new entry is added | 158 * a member of this or any other list. If existingEntry is NULL then the new entry is added |
115 * at the tail. | 159 * at the tail. |
116 */ | 160 */ |
117 void addBefore(T* newEntry, T* existingEntry) { | 161 void addBefore(T* newEntry, T* existingEntry) { |
118 SkASSERT(NULL != newEntry); | 162 SkASSERT(NULL != newEntry); |
119 | 163 |
120 if (NULL == existingEntry) { | 164 if (NULL == existingEntry) { |
121 this->addToTail(newEntry); | 165 this->addToTail(newEntry); |
122 return; | 166 return; |
123 } | 167 } |
124 | 168 |
125 SkASSERT(this->isInList(existingEntry)); | 169 SkASSERT(this->isInList(existingEntry)); |
126 newEntry->fNext = existingEntry; | 170 E::Next(newEntry) = existingEntry; |
127 T* prev = existingEntry->fPrev; | 171 T* prev = E::Prev(existingEntry); |
128 existingEntry->fPrev = newEntry; | 172 E::Prev(existingEntry) = newEntry; |
129 newEntry->fPrev = prev; | 173 E::Prev(newEntry) = prev; |
130 if (NULL == prev) { | 174 if (NULL == prev) { |
131 SkASSERT(fHead == existingEntry); | 175 SkASSERT(fHead == existingEntry); |
132 fHead = newEntry; | 176 fHead = newEntry; |
133 } else { | 177 } else { |
134 prev->fNext = newEntry; | 178 E::Next(prev) = newEntry; |
135 } | 179 } |
136 #ifdef SK_DEBUG | 180 #ifdef SK_DEBUG |
137 newEntry->fList = this; | 181 E::List(newEntry) = this; |
138 #endif | 182 #endif |
139 } | 183 } |
140 | 184 |
141 /** | 185 /** |
142 * Inserts a new list entry after an existing list entry. The new entry must not already be | 186 * Inserts a new list entry after an existing list entry. The new entry must not already be |
143 * a member of this or any other list. If existingEntry is NULL then the new entry is added | 187 * a member of this or any other list. If existingEntry is NULL then the new entry is added |
144 * at the head. | 188 * at the head. |
145 */ | 189 */ |
146 void addAfter(T* newEntry, T* existingEntry) { | 190 void addAfter(T* newEntry, T* existingEntry) { |
147 SkASSERT(NULL != newEntry); | 191 SkASSERT(NULL != newEntry); |
148 | 192 |
149 if (NULL == existingEntry) { | 193 if (NULL == existingEntry) { |
150 this->addToHead(newEntry); | 194 this->addToHead(newEntry); |
151 return; | 195 return; |
152 } | 196 } |
153 | 197 |
154 SkASSERT(this->isInList(existingEntry)); | 198 SkASSERT(this->isInList(existingEntry)); |
155 newEntry->fPrev = existingEntry; | 199 E::Prev(newEntry) = existingEntry; |
156 T* next = existingEntry->fNext; | 200 T* next = E::Next(existingEntry); |
157 existingEntry->fNext = newEntry; | 201 E::Next(existingEntry) = newEntry; |
158 newEntry->fNext = next; | 202 E::Next(newEntry) = next; |
159 if (NULL == next) { | 203 if (NULL == next) { |
160 SkASSERT(fTail == existingEntry); | 204 SkASSERT(fTail == existingEntry); |
161 fTail = newEntry; | 205 fTail = newEntry; |
162 } else { | 206 } else { |
163 next->fPrev = newEntry; | 207 E::Prev(next) = newEntry; |
164 } | 208 } |
165 #ifdef SK_DEBUG | 209 #ifdef SK_DEBUG |
166 newEntry->fList = this; | 210 E::List(newEntry) = this; |
167 #endif | 211 #endif |
168 } | 212 } |
169 | 213 |
170 bool isEmpty() const { | 214 bool isEmpty() const { |
171 return NULL == fHead && NULL == fTail; | 215 return NULL == fHead && NULL == fTail; |
172 } | 216 } |
173 | 217 |
174 T* head() { return fHead; } | 218 T* head() { return fHead; } |
175 T* tail() { return fTail; } | 219 T* tail() { return fTail; } |
176 | 220 |
(...skipping 22 matching lines...) Expand all Loading... | |
199 T* get() { return fCurr; } | 243 T* get() { return fCurr; } |
200 | 244 |
201 /** | 245 /** |
202 * Return the next/previous element in the list or NULL if at the end. | 246 * Return the next/previous element in the list or NULL if at the end. |
203 */ | 247 */ |
204 T* next() { | 248 T* next() { |
205 if (NULL == fCurr) { | 249 if (NULL == fCurr) { |
206 return NULL; | 250 return NULL; |
207 } | 251 } |
208 | 252 |
209 fCurr = fCurr->fNext; | 253 fCurr = E::Next(fCurr); |
210 return fCurr; | 254 return fCurr; |
211 } | 255 } |
212 | 256 |
213 T* prev() { | 257 T* prev() { |
214 if (NULL == fCurr) { | 258 if (NULL == fCurr) { |
215 return NULL; | 259 return NULL; |
216 } | 260 } |
217 | 261 |
218 fCurr = fCurr->fPrev; | 262 fCurr = E::Prev(fCurr); |
219 return fCurr; | 263 return fCurr; |
220 } | 264 } |
221 | 265 |
222 private: | 266 private: |
223 T* fCurr; | 267 T* fCurr; |
224 }; | 268 }; |
225 | 269 |
270 template <typename PredicateFunctor> | |
271 T* find(const PredicateFunctor& f) { | |
mtklein
2013/12/03 19:02:02
I'm still skeptical of adding a method like this.
| |
272 Iter iter; | |
273 for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != item; it em = iter.next()) { | |
274 if (f(item)) { | |
275 return item; | |
276 } | |
277 } | |
278 return NULL; | |
279 } | |
280 | |
226 #ifdef SK_DEBUG | 281 #ifdef SK_DEBUG |
227 void validate() const { | 282 void validate() const { |
228 SkASSERT(!fHead == !fTail); | 283 SkASSERT(!fHead == !fTail); |
229 Iter iter; | 284 Iter iter; |
230 for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != (item = iter.next()); ) { | 285 for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != item; i tem = iter.next()) { |
231 SkASSERT(this->isInList(item)); | 286 SkASSERT(this->isInList(item)); |
232 if (NULL == item->fPrev) { | 287 if (NULL == E::Prev(item)) { |
233 SkASSERT(fHead == item); | 288 SkASSERT(fHead == item); |
234 } else { | 289 } else { |
235 SkASSERT(item->fPrev->fNext == item); | 290 SkASSERT(E::Next(E::Prev(item)) == item); |
236 } | 291 } |
237 if (NULL == item->fNext) { | 292 if (NULL == E::Next(item)) { |
238 SkASSERT(fTail == item); | 293 SkASSERT(fTail == item); |
239 } else { | 294 } else { |
240 SkASSERT(item->fNext->fPrev == item); | 295 SkASSERT(E::Prev(E::Next(item)) == item); |
241 } | 296 } |
242 } | 297 } |
243 } | 298 } |
244 | 299 |
245 /** | 300 /** |
246 * Debugging-only method that uses the list back pointer to check if 'entry' is indeed in 'this' | 301 * Debugging-only method that uses the list back pointer to check if 'entry' is indeed in 'this' |
247 * list. | 302 * list. |
248 */ | 303 */ |
249 bool isInList(const T* entry) const { | 304 bool isInList(const T* entry) const { |
250 return entry->fList == this; | 305 return E::List(entry) == this; |
251 } | 306 } |
252 | 307 |
253 /** | 308 /** |
254 * Debugging-only method that laboriously counts the list entries. | 309 * Debugging-only method that laboriously counts the list entries. |
255 */ | 310 */ |
256 int countEntries() const { | 311 int countEntries() const { |
257 int count = 0; | 312 int count = 0; |
258 for (T* entry = fHead; NULL != entry; entry = entry->fNext) { | 313 for (T* entry = fHead; NULL != entry; entry = E::Next(entry)) { |
259 ++count; | 314 ++count; |
260 } | 315 } |
261 return count; | 316 return count; |
262 } | 317 } |
263 #endif // SK_DEBUG | 318 #endif // SK_DEBUG |
264 | 319 |
265 private: | 320 private: |
266 T* fHead; | 321 T* fHead; |
267 T* fTail; | 322 T* fTail; |
268 | 323 |
269 typedef SkNoncopyable INHERITED; | 324 typedef SkNoncopyable INHERITED; |
270 }; | 325 }; |
271 | 326 |
272 #endif | 327 #endif |
OLD | NEW |