00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef __ZDList__
00026 #define __ZDList__
00027 #include "zconfig.h"
00028
00029 #include "ZCompat_operator_bool.h"
00030 #include "ZDebug.h"
00031 #include "ZTypes.h"
00032
00033 namespace ZooLib {
00034
00035
00036
00037
00038 #pragma mark -
00039 #pragma mark * DListHead
00040
00041 template <typename L>
00042 struct DListHead
00043 {
00044 ZOOLIB_DEFINE_OPERATOR_BOOL_TYPES_T(DListHead, operator_bool_generator_type, operator_bool_type);
00045
00046 DListHead() : fHeadL(nil), fSize(0) {}
00047
00048 operator operator_bool_type() const { return operator_bool_generator_type::translate(fHeadL); }
00049
00050 size_t Size() const { return fSize; }
00051
00052 bool Empty() const
00053 {
00054 ZAssertStop(L::kDebug, (!fSize && !fHeadL) || (fSize && fHeadL));
00055 return !fHeadL;
00056 }
00057
00058 bool Contains(L* iL) const
00059 {
00060 return iL->fNext;
00061 }
00062
00063 void Insert(L* iL)
00064 {
00065 ZAssertStop(L::kDebug, !iL->fPrev);
00066 ZAssertStop(L::kDebug, !iL->fNext);
00067
00068 if (!fHeadL)
00069 {
00070 ZAssertStop(L::kDebug, fSize == 0);
00071 fSize = 1;
00072 fHeadL = iL;
00073 iL->fPrev = iL;
00074 iL->fNext = iL;
00075 }
00076 else
00077 {
00078 ZAssertStop(L::kDebug, fSize != 0);
00079 ++fSize;
00080 iL->fNext = fHeadL;
00081 iL->fPrev = fHeadL->fPrev;
00082 fHeadL->fPrev->fNext = iL;
00083 fHeadL->fPrev = iL;
00084 }
00085 }
00086
00087 void InsertIfNotContains(L* iL)
00088 {
00089 if (!iL->fNext)
00090 this->Insert(iL);
00091 }
00092
00093 void Remove(L* iL)
00094 {
00095 ZAssertStop(L::kDebug, fHeadL);
00096 ZAssertStop(L::kDebug, iL->fPrev);
00097 ZAssertStop(L::kDebug, iL->fNext);
00098
00099 if (iL->fPrev == iL)
00100 {
00101
00102 ZAssertStop(L::kDebug, iL->fNext == iL);
00103 ZAssertStop(L::kDebug, fHeadL == iL);
00104 ZAssertStop(L::kDebug, fSize == 1);
00105 fHeadL = nil;
00106 fSize = 0;
00107 }
00108 else
00109 {
00110 ZAssertStop(L::kDebug, fSize > 1);
00111 --fSize;
00112 if (fHeadL == iL)
00113 fHeadL = iL->fNext;
00114 iL->fNext->fPrev = iL->fPrev;
00115 iL->fPrev->fNext = iL->fNext;
00116 }
00117 iL->fNext = nil;
00118 iL->fPrev = nil;
00119 }
00120
00121 void RemoveIfContains(L* iL)
00122 {
00123 if (iL->fNext)
00124 this->Remove(iL);
00125 }
00126
00127 void PushFront(L* iL)
00128 {
00129 this->Insert(iL);
00130 fHeadL = iL;
00131 }
00132
00133 void PushBack(L* iL)
00134 {
00135 this->Insert(iL);
00136 }
00137
00138 template <typename P>
00139 P* PopFront()
00140 {
00141 ZAssertStop(L::kDebug, fHeadL);
00142 L* theL = fHeadL;
00143 this->Remove(theL);
00144 return static_cast<P*>(theL);
00145 }
00146
00147 template <typename P>
00148 P* PopBack()
00149 {
00150 ZAssertStop(L::kDebug, fHeadL);
00151 L* theL = fHeadL->fPrev;
00152 this->Remove(theL);
00153 return static_cast<P*>(theL);
00154 }
00155
00156 L* fHeadL;
00157 size_t fSize;
00158 };
00159
00160
00161 #pragma mark -
00162 #pragma mark * DListLink
00163
00164 template <typename P, typename L, int kDebug_T = 1>
00165 class DListLink
00166 {
00167 public:
00168
00169
00170 public:
00171 enum { kDebug = kDebug_T };
00172
00173 DListLink() : fPrev(nil), fNext(nil) {}
00174 ~DListLink() { ZAssertStop(kDebug, !fPrev && !fNext); }
00175 void Clear() { fPrev = nil; fNext = nil; }
00176
00177 L* fPrev;
00178 L* fNext;
00179 };
00180
00181
00182 #pragma mark -
00183 #pragma mark * DListIterator
00184
00185 template <typename P, typename L>
00186 class DListIterator
00187 {
00188 ZOOLIB_DEFINE_OPERATOR_BOOL_TYPES_T(DListIterator, operator_bool_generator_type, operator_bool_type);
00189 public:
00190 enum { kDebug = L::kDebug };
00191
00192 DListIterator(const ZooLib::DListHead<L>& iDListHead)
00193 : fDListHead(iDListHead),
00194 fCurrent(iDListHead.fHeadL)
00195 {}
00196
00197 operator operator_bool_type() const
00198 { return operator_bool_generator_type::translate(fCurrent); }
00199
00200 P* Current() const
00201 { return static_cast<P*>(fCurrent); }
00202
00203 void Advance()
00204 {
00205 ZAssertStop(kDebug, fCurrent);
00206 ZAssertStop(kDebug, fCurrent->fNext);
00207 fCurrent = fCurrent->fNext;
00208 if (fCurrent == fDListHead.fHeadL)
00209 fCurrent = nil;
00210 }
00211
00212 private:
00213 const ZooLib::DListHead<L>& fDListHead;
00214 L* fCurrent;
00215 };
00216
00217
00218 #pragma mark -
00219 #pragma mark * DListIteratorEraseAll
00220
00221 template <typename P, typename L>
00222 class DListIteratorEraseAll
00223 {
00224 ZOOLIB_DEFINE_OPERATOR_BOOL_TYPES_T(DListIteratorEraseAll, operator_bool_generator_type, operator_bool_type);
00225 public:
00226 enum { kDebug = L::kDebug };
00227
00228 DListIteratorEraseAll(ZooLib::DListHead<L>& ioDListHead)
00229 : fDListHead(ioDListHead),
00230 fCurrent(ioDListHead.fHeadL)
00231 {
00232 if (fCurrent)
00233 {
00234 ZAssertStop(kDebug, fCurrent->fNext);
00235 ZAssertStop(kDebug, fCurrent->fPrev);
00236 fNext = fCurrent->fNext;
00237 fCurrent->fNext = nil;
00238 fCurrent->fPrev = nil;
00239 }
00240 else
00241 {
00242 fNext = nil;
00243 }
00244 }
00245
00246 ~DListIteratorEraseAll()
00247 {
00248 fDListHead.fHeadL = nil;
00249 fDListHead.fSize = 0;
00250 }
00251
00252 operator operator_bool_type() const
00253 {
00254 ZAssertStop(kDebug, fCurrent && fNext || !fCurrent && !fNext);
00255 return operator_bool_generator_type::translate(fCurrent);
00256 }
00257
00258 P* Current() const
00259 { return static_cast<P*>(fCurrent); }
00260
00261 void Advance()
00262 {
00263 ZAssertStop(kDebug, fCurrent);
00264 ZAssertStop(kDebug, fNext);
00265 if (fNext == fDListHead.fHeadL)
00266 {
00267 fCurrent = nil;
00268 fNext = nil;
00269 }
00270 else
00271 {
00272 ZAssertStop(kDebug, fNext->fNext);
00273 fCurrent = fNext;
00274 fNext = fNext->fNext;
00275 fCurrent->fNext = nil;
00276 fCurrent->fPrev = nil;
00277 }
00278 }
00279
00280 private:
00281 ZooLib::DListHead<L>& fDListHead;
00282 L* fCurrent;
00283 L* fNext;
00284 };
00285
00286 }
00287
00288 #endif // __ZDList__