OpenMW
|
00001 #ifndef MISC_LIST_H 00002 #define MISC_LIST_H 00003 00004 #include <cassert> 00005 00006 namespace Misc{ 00007 00008 /* 00009 A simple and completely allocation-less doubly linked list. The 00010 class only manages pointers to and between elements. It leaving all 00011 memory management to the user. 00012 */ 00013 template <typename Elem> 00014 struct List 00015 { 00016 List() : head(0), tail(0), totalNum(0) {} 00017 00018 // Empty the list. 00019 void reset() 00020 { 00021 head = 0; 00022 tail = 0; 00023 totalNum = 0; 00024 } 00025 00026 // Insert an element at the end of the list. The element cannot be 00027 // part of any other list when this is called. 00028 void insert(Elem *p) 00029 { 00030 if(tail) 00031 { 00032 // There are existing elements. Insert the node at the end of 00033 // the list. 00034 assert(head && totalNum > 0); 00035 tail->next = p; 00036 } 00037 else 00038 { 00039 // This is the first element 00040 assert(head == 0 && totalNum == 0); 00041 head = p; 00042 } 00043 00044 // These have to be done in either case 00045 p->prev = tail; 00046 p->next = 0; 00047 tail = p; 00048 00049 totalNum++; 00050 } 00051 00052 // Remove element from the list. The element MUST be part of the 00053 // list when this is called. 00054 void remove(Elem *p) 00055 { 00056 assert(totalNum > 0); 00057 00058 if(p->next) 00059 { 00060 // There's an element following us. Set it up correctly. 00061 p->next->prev = p->prev; 00062 assert(tail && tail != p); 00063 } 00064 else 00065 { 00066 // We're the tail 00067 assert(tail == p); 00068 tail = p->prev; 00069 } 00070 00071 // Now do exactly the same for the previous element 00072 if(p->prev) 00073 { 00074 p->prev->next = p->next; 00075 assert(head && head != p); 00076 } 00077 else 00078 { 00079 assert(head == p); 00080 head = p->next; 00081 } 00082 00083 totalNum--; 00084 } 00085 00086 // Pop the first element off the list 00087 Elem *pop() 00088 { 00089 Elem *res = getHead(); 00090 if(res) remove(res); 00091 return res; 00092 } 00093 00094 // Swap the contents of this list with another of the same type 00095 void swap(List &other) 00096 { 00097 Elem *tmp; 00098 00099 tmp = head; 00100 head = other.head; 00101 other.head = tmp; 00102 00103 tmp = tail; 00104 tail = other.tail; 00105 other.tail = tmp; 00106 00107 unsigned int tmp2 = totalNum; 00108 totalNum = other.totalNum; 00109 other.totalNum = tmp2; 00110 } 00111 00112 /* Absorb the contents of another list. All the elements from the 00113 list are moved to the end of this list, and the other list is 00114 cleared. 00115 */ 00116 void absorb(List &other) 00117 { 00118 assert(&other != this); 00119 if(other.totalNum) 00120 { 00121 absorb(other.head, other.tail, other.totalNum); 00122 other.reset(); 00123 } 00124 assert(other.totalNum == 0); 00125 } 00126 00127 /* Absorb a range of elements, endpoints included. The elements are 00128 assumed NOT to belong to any list, but they ARE assumed to be 00129 connected with a chain between them. 00130 00131 The connection MUST run all the way from 'first' to 'last' 00132 through the ->next pointers, and vice versa through ->prev 00133 pointers. 00134 00135 The parameter 'num' must give the exact number of elements in the 00136 chain. 00137 00138 Passing first == last, num == 1 is allowed and is equivalent to 00139 calling insert(). 00140 */ 00141 void absorb(Elem* first, Elem *last, int num) 00142 { 00143 assert(first && last && num>=1); 00144 if(tail) 00145 { 00146 // There are existing elements. Insert the first node at the 00147 // end of the list. 00148 assert(head && totalNum > 0); 00149 tail->next = first; 00150 } 00151 else 00152 { 00153 // This is the first element 00154 assert(head == 0 && totalNum == 0); 00155 head = first; 00156 } 00157 00158 // These have to be done in either case 00159 first->prev = tail; 00160 last->next = 0; 00161 tail = last; 00162 00163 totalNum += num; 00164 } 00165 00166 Elem* getHead() const { return head; } 00167 Elem* getTail() const { return tail; } 00168 unsigned int getNum() const { return totalNum; } 00169 00170 private: 00171 00172 Elem *head; 00173 Elem *tail; 00174 unsigned int totalNum; 00175 }; 00176 00177 } 00178 #endif