2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkTInternalLList_DEFINED
9 #define SkTInternalLList_DEFINED
14 * Helper class to automatically initialize the doubly linked list created pointers.
16 template <typename T> class SkPtrWrapper {
18 SkPtrWrapper() : fPtr(NULL) {}
19 SkPtrWrapper& operator =(T* ptr) { fPtr = ptr; return *this; }
20 operator T*() const { return fPtr; }
21 T* operator->() { return fPtr; }
28 * This macro creates the member variables required by the SkTInternalLList class. It should be
29 * placed in the private section of any class that will be stored in a double linked list.
31 #define SK_DECLARE_INTERNAL_LLIST_INTERFACE(ClassName) \
32 friend class SkTInternalLList<ClassName>; \
33 /* back pointer to the owning list - for debugging */ \
34 SkDEBUGCODE(SkPtrWrapper<SkTInternalLList<ClassName> > fList;) \
35 SkPtrWrapper<ClassName> fPrev; \
36 SkPtrWrapper<ClassName> fNext
39 * This class implements a templated internal doubly linked list data structure.
41 template <class T> class SkTInternalLList : SkNoncopyable {
48 void remove(T* entry) {
49 SkASSERT(NULL != fHead && NULL != fTail);
50 SkASSERT(this->isInList(entry));
52 T* prev = entry->fPrev;
53 T* next = entry->fNext;
74 void addToHead(T* entry) {
75 SkASSERT(NULL == entry->fPrev && NULL == entry->fNext);
76 SkASSERT(NULL == entry->fList);
93 void addToTail(T* entry) {
94 SkASSERT(NULL == entry->fPrev && NULL == entry->fNext);
95 SkASSERT(NULL == entry->fList);
100 fTail->fNext = entry;
113 * Inserts a new list entry before an existing list entry. The new entry must not already be
114 * a member of this or any other list. If existingEntry is NULL then the new entry is added
117 void addBefore(T* newEntry, T* existingEntry) {
118 SkASSERT(NULL != newEntry);
120 if (NULL == existingEntry) {
121 this->addToTail(newEntry);
125 SkASSERT(this->isInList(existingEntry));
126 newEntry->fNext = existingEntry;
127 T* prev = existingEntry->fPrev;
128 existingEntry->fPrev = newEntry;
129 newEntry->fPrev = prev;
131 SkASSERT(fHead == existingEntry);
134 prev->fNext = newEntry;
137 newEntry->fList = this;
142 * 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
146 void addAfter(T* newEntry, T* existingEntry) {
147 SkASSERT(NULL != newEntry);
149 if (NULL == existingEntry) {
150 this->addToHead(newEntry);
154 SkASSERT(this->isInList(existingEntry));
155 newEntry->fPrev = existingEntry;
156 T* next = existingEntry->fNext;
157 existingEntry->fNext = newEntry;
158 newEntry->fNext = next;
160 SkASSERT(fTail == existingEntry);
163 next->fPrev = newEntry;
166 newEntry->fList = this;
170 bool isEmpty() const {
171 return NULL == fHead && NULL == fTail;
174 T* head() { return fHead; }
175 T* tail() { return fTail; }
184 Iter() : fCurr(NULL) {}
185 Iter(const Iter& iter) : fCurr(iter.fCurr) {}
186 Iter& operator= (const Iter& iter) { fCurr = iter.fCurr; return *this; }
188 T* init(const SkTInternalLList& list, IterStart startLoc) {
189 if (kHead_IterStart == startLoc) {
192 SkASSERT(kTail_IterStart == startLoc);
199 T* get() { return fCurr; }
202 * Return the next/previous element in the list or NULL if at the end.
209 fCurr = fCurr->fNext;
218 fCurr = fCurr->fPrev;
227 void validate() const {
228 SkASSERT(!fHead == !fTail);
230 for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != item; item = iter.next()) {
231 SkASSERT(this->isInList(item));
232 if (NULL == item->fPrev) {
233 SkASSERT(fHead == item);
235 SkASSERT(item->fPrev->fNext == item);
237 if (NULL == item->fNext) {
238 SkASSERT(fTail == item);
240 SkASSERT(item->fNext->fPrev == item);
246 * Debugging-only method that uses the list back pointer to check if 'entry' is indeed in 'this'
249 bool isInList(const T* entry) const {
250 return entry->fList == this;
254 * Debugging-only method that laboriously counts the list entries.
256 int countEntries() const {
258 for (T* entry = fHead; NULL != entry; entry = entry->fNext) {
269 typedef SkNoncopyable INHERITED;