00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Cristin Barghiel 00008 * Side Effects Software Inc. 00009 * 20 Maud St. 00010 * Toronto, Ontario, M5V 2M5 00011 * Canada 00012 * 416-366-4607 00013 * 00014 * NAME: Utility Library (C++) 00015 * 00016 * COMMENTS: 00017 * This class implements a doubly linked list that maintains 00018 * a replacement list of nodes. 00019 * 00020 */ 00021 00022 #ifndef __UT_LinkList_h__ 00023 #define __UT_LinkList_h__ 00024 00025 #include "UT_API.h" 00026 #include "UT_Algorithm.h" 00027 #include <iostream.h> 00028 00029 class UT_API UT_LinkNode { 00030 public: 00031 // Constructor and destructor: 00032 UT_LinkNode(void) { predNode = succNode = 0; } 00033 virtual ~UT_LinkNode(void); 00034 00035 // Query/set methods: 00036 UT_LinkNode *&prev() { return predNode; } 00037 UT_LinkNode *&next() { return succNode; } 00038 const UT_LinkNode *prev() const { return predNode; } 00039 const UT_LinkNode *next() const { return succNode; } 00040 00041 // I/O friends: 00042 friend ostream &operator<<(ostream &os, const UT_LinkNode &n) 00043 { 00044 n.outTo(os); 00045 return os; 00046 } 00047 00048 protected: 00049 // Query the name of this class: 00050 virtual const char *className(void) const; 00051 00052 // Our own I/O methods, so we can redefine them in derived classes: 00053 virtual void outTo (ostream &os) const; 00054 00055 private: 00056 // Pointers to predecessor and successor respectively: 00057 UT_LinkNode *predNode; 00058 UT_LinkNode *succNode; 00059 }; 00060 00061 00062 class UT_API UT_LinkList { 00063 public: 00064 // Trivial class constructor and destructor. The destructor 00065 // deallocates every node in the active and replacement lists. 00066 UT_LinkList(void) { first=last=stashHead=0; count=0; } 00067 virtual ~UT_LinkList(void); 00068 00069 void swap( UT_LinkList &other ); 00070 00071 // Reverse the order of the active nodes: 00072 virtual void reverse(void); 00073 00074 // Add nodes to the list, or delete them: 00075 // append() appends a node, insert() inserts it at index 'where'; 00076 // remove() deletes the node from the list and leaves it intact; 00077 // destroy() deletes the node from the list and deallocates it. 00078 // If the node is not in the list, or if nodeIdx is invalid, 00079 // both remove() and destroy() return 0. If the node is 0, 00080 // remove() and destroy() will act upon the last element in the 00081 // list. None of the functions below checks whether the node 00082 // is or is not in the list at the time it is deleted or added. 00083 // To check for existence, see inList(). 00084 void append (UT_LinkNode *node); 00085 void insert (UT_LinkNode *node, int where); 00086 // node is the node to insert, before and after are the node already 00087 // in the list that you wish to insert before/after. 00088 void insertBefore(UT_LinkNode *node, UT_LinkNode *before); 00089 void insertAfter(UT_LinkNode *node, UT_LinkNode *after); 00090 00091 UT_LinkNode *remove (UT_LinkNode *node = 0); 00092 UT_LinkNode *remove (int nodeIdx); 00093 void destroy(UT_LinkNode *node = 0); 00094 void destroy(int nodeIdx); 00095 00096 // Take a node from the active list and stash it into the 00097 // replacement list. recall() performs the inverse procedure. 00098 // If the node parameter is 0, stash and recall will act upon 00099 // the last elemenent added to the respective list. 00100 UT_LinkNode *stash (UT_LinkNode *node = 0); 00101 UT_LinkNode *stash (int nodeIdx); 00102 UT_LinkNode *recall(UT_LinkNode *node = 0); 00103 UT_LinkNode *recall(UT_LinkNode *node, int nodeIdx); 00104 00105 // Return the index of the node in the list or vice-versa. 00106 // The first method returns -1 if not found; the 2nd method 00107 // returns 0 if unsuccessful. 00108 int find(UT_LinkNode *node) const; 00109 UT_LinkNode *find(int nodeIdx) const; 00110 00111 // Check if the node is in the active list: return 1 if true, o if 00112 // false. 00113 int inList(UT_LinkNode *node) const; 00114 00115 00116 // Return the predecessor or the successor of a node, or the 00117 // first or last node in the list respectively. 00118 UT_LinkNode *prev(UT_LinkNode *node) const { return node->prev(); } 00119 UT_LinkNode *next(UT_LinkNode *node) const { return node->next(); } 00120 UT_LinkNode *head() const { return first; } 00121 UT_LinkNode *tail() const { return last; } 00122 00123 // Some iteration functions, in case you are not using the separate 00124 // iterator class: 00125 UT_LinkNode *iterateInit() const { return first; } 00126 UT_LinkNode *iterateNext(UT_LinkNode *curr) const 00127 { 00128 return curr ? curr->next() : first; 00129 } 00130 UT_LinkNode *iteratePrev(UT_LinkNode *curr) const 00131 { 00132 return curr ? curr->prev() : last; 00133 } 00134 UT_LinkNode *iterateFastNext(UT_LinkNode *curr) const {return curr->next();} 00135 UT_LinkNode *iterateFastPrev(UT_LinkNode *curr) const {return curr->prev();} 00136 00137 // Clear the linked list: the list of stashed nodes, the active 00138 // list, or both. 00139 void clearStashed(); 00140 void clearActive(); 00141 void clear() { clearActive(); clearStashed(); } 00142 00143 // Return the length of the list or just find out whether it's empty. 00144 int length() const { return count; } 00145 int isEmpty() const { return count == 0; } 00146 00147 // Apply a user-defined function to each element of the linked 00148 // list, as long as the function returns zero. If applyFct returns 00149 // 0, apply() stops traversing the list and returns the current 00150 // node; otherwise, apply() returns 0. 00151 UT_LinkNode *apply(int (*applyFct)(UT_LinkNode *n, void *d), void *d); 00152 00153 // Copy the other list's data into us. The source gets cleared. 00154 UT_LinkList &operator=(UT_LinkList &src); 00155 00156 // Append the other list's data to ours. The source gets cleared. 00157 UT_LinkList &operator+=(UT_LinkList &src); 00158 00159 // I/O friends: 00160 friend ostream &operator<<(ostream &os, const UT_LinkList &v) 00161 { 00162 v.outTo(os); 00163 return os; 00164 } 00165 00166 protected: 00167 // Current node of iteration, in case you are not using the iterator class. 00168 // Remove a node from the replacement list. Remove the last 00169 // one inserted if 0. 00170 UT_LinkNode *unStash(UT_LinkNode *node = 0); 00171 00172 // Query the stash head: 00173 UT_LinkNode *firstStash() const { return stashHead; } 00174 00175 // Query the name of this class: 00176 virtual const char *className(void) const; 00177 00178 // Our own I/O methods, so we can redefine them in derived classes: 00179 virtual void outTo (ostream &os) const; 00180 00181 // Head of the stash list. 00182 UT_LinkNode *stashHead; 00183 00184 // Just reset the state of the link list 00185 // Not, this will cause memory leaks unless used with caution, 00186 // ie. list sorting 00187 void reset() { first = last = 0; count = 0; } 00188 00189 00190 private: 00191 00192 // DATA 00193 00194 // First and last nodes in the active list. 00195 UT_LinkNode *first; 00196 UT_LinkNode *last; 00197 00198 // Number of nodes in the active list. 00199 int count; 00200 }; 00201 00202 UT_SWAPPER_CLASS( UT_LinkList ) 00203 00204 #endif
1.5.9