aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-23 11:13:48 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-23 11:13:48 +0000
commit2ea0a231a82b00e14c57806f6ae4664361d2ed16 (patch)
tree5dcf2d980dd521b8c7d5a109bb9ba169517696ca /include/core
parentc59b5dac9081e3613ed80d8b6d498e093c03eb87 (diff)
Refactored GrDLinkedList into SkTDLinkedList
Diffstat (limited to 'include/core')
-rw-r--r--include/core/SkTDLinkedList.h175
1 files changed, 175 insertions, 0 deletions
diff --git a/include/core/SkTDLinkedList.h b/include/core/SkTDLinkedList.h
new file mode 100644
index 0000000000..5dfad55c71
--- /dev/null
+++ b/include/core/SkTDLinkedList.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTDLinkedList_DEFINED
+#define SkTDLinkedList_DEFINED
+
+#include "SkTypes.h"
+
+/**
+ * Helper class to automatically initialize the doubly linked list
+ * created pointers.
+ */
+template <typename T> class SkPtrWrapper {
+ public:
+ SkPtrWrapper() : fPtr(NULL) {}
+ SkPtrWrapper& operator =(T* ptr) { fPtr = ptr; return *this; }
+ operator T*() const { return fPtr; }
+ T* operator->() { return fPtr; }
+ private:
+ T* fPtr;
+};
+
+
+/**
+ * This macro creates the member variables required by
+ * the SkTDLinkedList class. It should be placed in the private section
+ * of any class that will be stored in a double linked list.
+ */
+#define SK_DEFINE_DLINKEDLIST_INTERFACE(ClassName) \
+ friend class SkTDLinkedList<ClassName>; \
+ /* back pointer to the owning list - for debugging */ \
+ SkDEBUGCODE(SkPtrWrapper<SkTDLinkedList<ClassName> > fList;)\
+ SkPtrWrapper<ClassName> fPrev; \
+ SkPtrWrapper<ClassName> fNext;
+
+/**
+ * This class implements a templated internal doubly linked list data structure.
+ */
+template <class T> class SkTDLinkedList : public SkNoncopyable {
+public:
+ SkTDLinkedList()
+ : fHead(NULL)
+ , fTail(NULL) {
+ }
+
+ void remove(T* entry) {
+ SkASSERT(this->isInList(entry));
+
+ T* prev = entry->fPrev;
+ T* next = entry->fNext;
+
+ if (NULL != prev) {
+ prev->fNext = next;
+ } else {
+ fHead = next;
+ }
+ if (NULL != next) {
+ next->fPrev = prev;
+ } else {
+ fTail = prev;
+ }
+
+ entry->fPrev = NULL;
+ entry->fNext = NULL;
+
+#if SK_DEBUG
+ entry->fList = NULL;
+#endif
+ }
+
+ void addToHead(T* entry) {
+ SkASSERT(NULL == entry->fPrev && NULL == entry->fNext);
+ SkASSERT(NULL == entry->fList);
+
+ entry->fPrev = NULL;
+ entry->fNext = fHead;
+ if (NULL != fHead) {
+ fHead->fPrev = entry;
+ }
+ fHead = entry;
+ if (NULL == fTail) {
+ fTail = entry;
+ }
+
+#if SK_DEBUG
+ entry->fList = this;
+#endif
+ }
+
+ bool isEmpty() const {
+ return NULL == fHead && NULL == fTail;
+ }
+
+ class Iter {
+ public:
+ enum IterStart {
+ kHead_IterStart,
+ kTail_IterStart
+ };
+
+ Iter() : fCur(NULL) {}
+
+ T* init(SkTDLinkedList& list, IterStart startLoc) {
+ if (kHead_IterStart == startLoc) {
+ fCur = list.fHead;
+ } else {
+ SkASSERT(kTail_IterStart == startLoc);
+ fCur = list.fTail;
+ }
+
+ return fCur;
+ }
+
+ /**
+ * Return the next/previous element in the list or NULL if at the end.
+ */
+ T* next() {
+ if (NULL == fCur) {
+ return NULL;
+ }
+
+ fCur = fCur->fNext;
+ return fCur;
+ }
+
+ T* prev() {
+ if (NULL == fCur) {
+ return NULL;
+ }
+
+ fCur = fCur->fPrev;
+ return fCur;
+ }
+
+ private:
+ T* fCur;
+ };
+
+#if SK_DEBUG
+ void validate() const {
+ GrAssert(!fHead == !fTail);
+ }
+
+ /**
+ * Debugging-only method that uses the list back pointer to check if
+ * 'entry' is indeed in 'this' list.
+ */
+ bool isInList(const T* entry) const {
+ return entry->fList == this;
+ }
+
+ /**
+ * Debugging-only method that laboriously counts the list entries.
+ */
+ int countEntries() const {
+ int count = 0;
+ for (T* entry = fHead; NULL != entry; entry = entry->fNext) {
+ ++count;
+ }
+ return count;
+ }
+#endif // SK_DEBUG
+
+private:
+ T* fHead;
+ T* fTail;
+
+ typedef SkNoncopyable INHERITED;
+};
+
+#endif // SkTDLinkedList_DEFINED