00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef _NPT_LIST_H_
00011 #define _NPT_LIST_H_
00012
00013
00014
00015
00016 #include "NptResults.h"
00017 #include "NptTypes.h"
00018 #include "NptConstants.h"
00019 #include "NptCommon.h"
00020
00021
00022
00023
00024 const int NPT_ERROR_LIST_EMPTY = NPT_ERROR_BASE_LIST - 0;
00025 const int NPT_ERROR_LIST_OPERATION_ABORTED = NPT_ERROR_BASE_LIST - 1;
00026 const int NPT_ERROR_LIST_OPERATION_CONTINUE = NPT_ERROR_BASE_LIST - 2;
00027
00028
00029
00030
00031 template <typename T>
00032 class NPT_List
00033 {
00034 protected:
00035 class Item;
00036
00037 public:
00038
00039 typedef T Element;
00040
00041 class Iterator {
00042 public:
00043 Iterator() : m_Item(NULL) {}
00044 explicit Iterator(Item* item) : m_Item(item) {}
00045 Iterator(const Iterator& copy) : m_Item(copy.m_Item) {}
00046 T& operator*() const { return m_Item->m_Data; }
00047 T* operator->() const { return &m_Item->m_Data;}
00048 Iterator& operator++() {
00049 m_Item = m_Item->m_Next;
00050 return (*this);
00051 }
00052 Iterator operator++(int) {
00053 Iterator saved_this = *this;
00054 m_Item = m_Item->m_Next;
00055 return saved_this;
00056 }
00057 Iterator& operator--() {
00058 m_Item = m_Item->m_Prev;
00059 return (*this);
00060 }
00061 Iterator operator--(int) {
00062 Iterator saved_this = *this;
00063 m_Item = m_Item->m_Prev;
00064 return saved_this;
00065 }
00066 operator bool() const {
00067 return m_Item != NULL;
00068 }
00069 bool operator==(const Iterator& other) const {
00070 return m_Item == other.m_Item;
00071 }
00072 bool operator!=(const Iterator& other) const {
00073 return m_Item != other.m_Item;
00074 }
00075 void operator=(const Iterator& other) {
00076 m_Item = other.m_Item;
00077 }
00078 void operator=(Item* item) {
00079 m_Item = item;
00080 }
00081
00082 private:
00083 Item* m_Item;
00084
00085
00086 friend class NPT_List<T>;
00087 };
00088
00089
00090 NPT_List<T>();
00091 NPT_List<T>(const NPT_List<T>& list);
00092 ~NPT_List<T>();
00093 NPT_Result Add(const T& data);
00094 NPT_Result Insert(const Iterator where, const T& data);
00095 NPT_Result Remove(const T& data, bool all=false);
00096 NPT_Result Erase(const Iterator position);
00097 NPT_Result PopHead(T& data);
00098 bool Contains(const T& data) const;
00099 NPT_Result Clear();
00100 NPT_Result Get(NPT_Ordinal index, T& data) const;
00101 NPT_Result Get(NPT_Ordinal index, T*& data) const;
00102 NPT_Cardinal GetItemCount() const { return m_ItemCount; }
00103 Iterator GetFirstItem() const { return Iterator(m_Head); }
00104 Iterator GetLastItem() const { return Iterator(m_Tail); }
00105 Iterator GetItem(NPT_Ordinal index) const;
00106
00107
00108 NPT_Result Add(Item& item);
00109 NPT_Result Detach(Item& item);
00110 NPT_Result Insert(const Iterator where, Item& item);
00111
00112
00113
00114
00115 template <typename X>
00116 NPT_Result Apply(const X& function) const
00117 {
00118 Item* item = m_Head;
00119 while (item) {
00120 function(item->m_Data);
00121 item = item->m_Next;
00122 }
00123
00124 return NPT_SUCCESS;
00125 }
00126
00127 template <typename X, typename P>
00128 NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
00129 {
00130 Item* item = m_Head;
00131 while (item) {
00132 NPT_Result return_value;
00133 if (predicate(function(item->m_Data), return_value)) {
00134 if (match) *match = true;
00135 return return_value;
00136 }
00137 item = item->m_Next;
00138 }
00139
00140 if (match) *match = false;
00141 return NPT_SUCCESS;
00142 }
00143
00144 template <typename P>
00145 Iterator Find(const P& predicate, NPT_Ordinal n=0) const
00146 {
00147 Item* item = m_Head;
00148 while (item) {
00149 if (predicate(item->m_Data)) {
00150 if (n == 0) {
00151 return Iterator(item);
00152 }
00153 --n;
00154 }
00155 item = item->m_Next;
00156 }
00157
00158 return Iterator(NULL);
00159 }
00160
00161
00162 void operator=(const NPT_List<T>& other);
00163 bool operator==(const NPT_List<T>& other) const;
00164 bool operator!=(const NPT_List<T>& other) const;
00165
00166 protected:
00167
00168 class Item
00169 {
00170 public:
00171
00172 Item(const T& data) : m_Next(0), m_Prev(0), m_Data(data) {}
00173
00174
00175 Item* m_Next;
00176 Item* m_Prev;
00177 T m_Data;
00178
00179
00180
00181
00182 };
00183
00184
00185 NPT_Cardinal m_ItemCount;
00186 Item* m_Head;
00187 Item* m_Tail;
00188 };
00189
00190
00191
00192
00193 template <typename T>
00194 inline
00195 NPT_List<T>::NPT_List() : m_ItemCount(0), m_Head(0), m_Tail(0)
00196 {
00197 }
00198
00199
00200
00201
00202 template <typename T>
00203 inline
00204 NPT_List<T>::NPT_List(const NPT_List<T>& list) : m_ItemCount(0), m_Head(0), m_Tail(0)
00205 {
00206 *this = list;
00207 }
00208
00209
00210
00211
00212 template <typename T>
00213 inline
00214 NPT_List<T>::~NPT_List()
00215 {
00216 Clear();
00217 }
00218
00219
00220
00221
00222 template <typename T>
00223 void
00224 NPT_List<T>::operator=(const NPT_List<T>& list)
00225 {
00226
00227 Clear();
00228
00229
00230 Item* item = list.m_Head;
00231 while (item) {
00232 Add(item->m_Data);
00233 item = item->m_Next;
00234 }
00235 }
00236
00237
00238
00239
00240 template <typename T>
00241 bool
00242 NPT_List<T>::operator==(const NPT_List<T>& other) const
00243 {
00244
00245 if (m_ItemCount != other.m_ItemCount) return false;
00246
00247
00248 Item* our_item = m_Head;
00249 Item* their_item = other.m_Head;
00250 while (our_item && their_item) {
00251 if (our_item->m_Data != their_item->m_Data) return false;
00252 our_item = our_item->m_Next;
00253 their_item = their_item->m_Next;
00254 }
00255
00256 return our_item == NULL && their_item == NULL;
00257 }
00258
00259
00260
00261
00262 template <typename T>
00263 inline
00264 bool
00265 NPT_List<T>::operator!=(const NPT_List<T>& other) const
00266 {
00267 return !(*this == other);
00268 }
00269
00270
00271
00272
00273 template <typename T>
00274 NPT_Result
00275 NPT_List<T>::Clear()
00276 {
00277
00278 Item* item = m_Head;
00279 while (item) {
00280 Item* next = item->m_Next;
00281 delete item;
00282 item = next;
00283 }
00284
00285 m_ItemCount = 0;
00286 m_Head = NULL;
00287 m_Tail = NULL;
00288
00289 return NPT_SUCCESS;
00290 }
00291
00292
00293
00294
00295 template <typename T>
00296 NPT_Result
00297 NPT_List<T>::Add(Item& item)
00298 {
00299
00300 if (m_Tail) {
00301 item.m_Prev = m_Tail;
00302 item.m_Next = NULL;
00303 m_Tail->m_Next = &item;
00304 m_Tail = &item;
00305 } else {
00306 m_Head = &item;
00307 m_Tail = &item;
00308 item.m_Next = NULL;
00309 item.m_Prev = NULL;
00310 }
00311
00312
00313 ++m_ItemCount;
00314
00315 return NPT_SUCCESS;
00316 }
00317
00318
00319
00320
00321 template <typename T>
00322 inline
00323 NPT_Result
00324 NPT_List<T>::Add(const T& data)
00325 {
00326 return Add(*new Item(data));
00327 }
00328
00329
00330
00331
00332 template <typename T>
00333 typename NPT_List<T>::Iterator
00334 NPT_List<T>::GetItem(NPT_Ordinal n) const
00335 {
00336 Iterator result;
00337 if (n >= m_ItemCount) return result;
00338
00339 result = m_Head;
00340 for (unsigned int i=0; i<n; i++) {
00341 ++result;
00342 }
00343
00344 return result;
00345 }
00346
00347
00348
00349
00350 template <typename T>
00351 inline NPT_Result
00352 NPT_List<T>::Insert(Iterator where, const T&data)
00353 {
00354 return Insert(where, *new Item(data));
00355 }
00356
00357
00358
00359
00360 template <typename T>
00361 NPT_Result
00362 NPT_List<T>::Insert(Iterator where, Item& item)
00363 {
00364
00365 Item* position = where.m_Item;
00366 if (position) {
00367
00368 item.m_Next = position;
00369 item.m_Prev = position->m_Prev;
00370 position->m_Prev = &item;
00371 if (item.m_Prev) {
00372 item.m_Prev->m_Next = &item;
00373 } else {
00374
00375 m_Head = &item;
00376 }
00377
00378
00379 ++m_ItemCount;
00380 } else {
00381
00382 return Add(item);
00383 }
00384
00385 return NPT_SUCCESS;
00386 }
00387
00388
00389
00390
00391 template <typename T>
00392 NPT_Result
00393 NPT_List<T>::Erase(Iterator position)
00394 {
00395 if (!position) return NPT_ERROR_NO_SUCH_ITEM;
00396 Detach(*position.m_Item);
00397 delete position.m_Item;
00398
00399 return NPT_SUCCESS;
00400 }
00401
00402
00403
00404
00405 template <typename T>
00406 NPT_Result
00407 NPT_List<T>::Remove(const T& data, bool all)
00408 {
00409 Item* item = m_Head;
00410 NPT_Cardinal matches = 0;
00411
00412 while (item) {
00413 Item* next = item->m_Next;
00414 if (item->m_Data == data) {
00415
00416 ++matches;
00417
00418
00419 Detach(*item);
00420
00421
00422 delete item;
00423
00424 if (!all) return NPT_SUCCESS;
00425 }
00426 item = next;
00427 }
00428
00429 return matches?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM;
00430 }
00431
00432
00433
00434
00435 template <typename T>
00436 NPT_Result
00437 NPT_List<T>::Detach(Item& item)
00438 {
00439
00440 if (item.m_Prev) {
00441
00442 if (item.m_Next) {
00443
00444 item.m_Next->m_Prev = item.m_Prev;
00445 item.m_Prev->m_Next = item.m_Next;
00446 } else {
00447
00448 m_Tail = item.m_Prev;
00449 m_Tail->m_Next = NULL;
00450 }
00451 } else {
00452
00453 m_Head = item.m_Next;
00454 if (m_Head) {
00455
00456 m_Head->m_Prev = NULL;
00457 } else {
00458
00459 m_Tail = NULL;
00460 }
00461 }
00462
00463
00464 --m_ItemCount;
00465
00466 return NPT_SUCCESS;
00467 }
00468
00469
00470
00471
00472 template <typename T>
00473 NPT_Result
00474 NPT_List<T>::Get(NPT_Ordinal index, T& data) const
00475 {
00476 T* data_pointer;
00477 NPT_CHECK(Get(index, data_pointer));
00478 data = *data_pointer;
00479 return NPT_SUCCESS;
00480 }
00481
00482
00483
00484
00485 template <typename T>
00486 NPT_Result
00487 NPT_List<T>::Get(NPT_Ordinal index, T*& data) const
00488 {
00489 Item* item = m_Head;
00490
00491 if (index < m_ItemCount) {
00492 while (index--) item = item->m_Next;
00493 data = &item->m_Data;
00494 return NPT_SUCCESS;
00495 } else {
00496 data = NULL;
00497 return NPT_ERROR_NO_SUCH_ITEM;
00498 }
00499 }
00500
00501
00502
00503
00504 template <typename T>
00505 NPT_Result
00506 NPT_List<T>::PopHead(T& data)
00507 {
00508
00509 if (m_Head == NULL) return NPT_ERROR_LIST_EMPTY;
00510
00511
00512 data = m_Head->m_Data;
00513
00514
00515 Item* head = m_Head;
00516 m_Head = m_Head->m_Next;
00517 if (m_Head) {
00518 m_Head->m_Prev = NULL;
00519 } else {
00520 m_Tail = NULL;
00521 }
00522 delete head;
00523
00524
00525 --m_ItemCount;
00526
00527 return NPT_SUCCESS;
00528 }
00529
00530
00531
00532
00533 template <typename T>
00534 bool
00535 NPT_List<T>::Contains(const T& data) const
00536 {
00537 Item* item = m_Head;
00538 while (item) {
00539 if (item->m_Data == data) return true;
00540 item = item->m_Next;
00541 }
00542
00543 return false;
00544 }
00545
00546 #endif // _NPT_LIST_H_