00001 #ifndef _CMT_MONOLITHIC 00002 /*! \file 00003 \brief List class interface for use in CMT 00004 00005 The implementations of the functions are in \ref Cmtlist.hpp which is automatically 00006 included so they are inlined. 00007 00008 This file requires xsens_janitors.h. When a library header is built with this file, 00009 make sure xsens_janitors.h is included before this file. 00010 00011 This file requires xsens_math.h if the math switch is set to 1. When a library header 00012 is built with this file, make sure xsens_math.h is included before this file. 00013 00014 \section FileCopyright Copyright Notice 00015 Copyright (C) Xsens Technologies B.V., 2006. All rights reserved. 00016 00017 This source code is intended for use only by Xsens Technologies BV and 00018 those that have explicit written permission to use it from 00019 Xsens Technologies BV. 00020 00021 THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 00022 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 00023 IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 00024 PARTICULAR PURPOSE. 00025 00026 \section FileSwitches Switches 00027 \li \c _XSENS_LIST_WITH_MATH Check whether to include math files when set to 1. 00028 \li \c _XSENS_LIST_IO Include code for string and file I/O when set to 1. 00029 */ 00030 #endif 00031 #ifndef _XSENS_LIST_H_2006_06_08 00032 #define _XSENS_LIST_H_2006_06_08 00033 00034 #ifndef _CMT_MONOLITHIC 00035 #ifndef _PSTDINT_H_INCLUDED 00036 # include "pstdint.h" 00037 #endif 00038 #endif 00039 00040 #ifndef _JANITORS_H_2006_05_01 00041 # include "xsens_janitors.h" 00042 #endif 00043 00044 00045 #define XSENS_LIST_NOTFOUND 0xFFFFFFFF 00046 00047 #ifdef _XSENS_LIST_RANGE_CHECKS 00048 # ifdef _MSC_VER 00049 # define XSENS_LIST_THROW throw(...) 00050 # else 00051 # define XSENS_LIST_THROW 00052 # endif 00053 #else 00054 # define XSENS_LIST_THROW 00055 #endif 00056 00057 #include <stdlib.h> 00058 #include <malloc.h> 00059 00060 namespace xsens { 00061 00062 #define CMT_LIST_LINEAR_SEARCH_TRESHOLD 10 00063 00064 /*! \brief Dynamic list class 00065 00066 This class can store items of the given type. If the type supports the < operator 00067 it can also be sorted. 00068 Items in the list can be accessed through the [] operator or the get() function. 00069 00070 Do NOT use any item type that requires a constructor to work correctly. Pointers to these 00071 objects can work though. 00072 */ 00073 template <typename T> 00074 class List 00075 { 00076 private: 00077 void operator = (const List& list); //!< intentionally NOT implemented due to ambiguous nature 00078 //! Sorts the list in an ascending order, using the T::< operator. 00079 void qSort(uint32_t left, uint32_t right); 00080 //! Sorts the list in an ascending order, using the T::< operator on dereferenced list items. 00081 void qSortDeref(uint32_t left, uint32_t right); 00082 00083 protected: 00084 T* m_data; //!< The array containing the items 00085 uint32_t m_max; //!< The current size of the data array 00086 uint32_t m_count; //!< The number of items currently in the list 00087 JanitorClassFunc<List<T> >* m_jcf; //!< Used to clean up the list on exit 00088 bool m_manage; 00089 00090 //! Construct a list as a reference to a raw list 00091 List(const uint32_t size, T* src, bool manage); 00092 public: 00093 00094 //! A comparison function type, should return -1, 0 or 1 for <, == and > 00095 typedef int32_t (*cmpFunc) (const T&,const T&); 00096 00097 //! Standard constructor, creates an empty list with some room for items. 00098 List(); 00099 //! Construct a list with a capacity of at least the given size. 00100 List(const uint32_t size); 00101 //! Construct a list as a direct copy of another list 00102 List(const List<T>& src); 00103 //! Construct a list as a copy of a raw list 00104 List(const uint32_t size, const T* src); 00105 //! Destroy the list. This does NOT automatically delete items IN the list. 00106 ~List(); 00107 00108 //! Calls delete for all items in the list and then clears the list. 00109 void deleteAndClear(void); 00110 //! Calls free for all items in the list and then clears the list. 00111 void freeAndClear(void); 00112 //! Clears the list without explicitly deleting anything. 00113 void clear(void); 00114 //! Resizes the list to at least the given size. 00115 void resize(uint32_t newSize); 00116 //! Adds an item to the end of the list. 00117 void append(const T& item); 00118 //! Adds a number of items to the end of the list. 00119 void appendList(uint32_t count, const T* lst); 00120 //! Adds the contents of the source list to the end of the list. 00121 void appendDeepCopy(const List<T>& source); 00122 //! Adds the contents of the source list to the end of the list. 00123 void appendShallowCopy(const List<T>& source); 00124 //! Adds a copy of a referenced item to the end of the list using newItem = new TB(item). 00125 template <typename TB> 00126 void appendCopy(const TB& item); 00127 //! Adds a related item to the end of the list, using the T = TR operator. 00128 template <typename TR> 00129 void appendRelated(const TR& item); 00130 //! Removes an item at the given index in the list. 00131 void remove(const uint32_t index) XSENS_LIST_THROW; 00132 //! Swaps two items in the list. 00133 void swap(const uint32_t i, const uint32_t j) XSENS_LIST_THROW; 00134 //! Removes an item at the given index in the list. 00135 void deleteAndRemove(const uint32_t index) XSENS_LIST_THROW; 00136 //! Removes an item at the given index in the list. 00137 void freeAndRemove(const uint32_t index) XSENS_LIST_THROW; 00138 //! Retrieves the last item. 00139 T& last(void) const XSENS_LIST_THROW; 00140 //! Retrieves the item at the given index. An index beyond the end returns the first item. 00141 T& get(const uint32_t index) const XSENS_LIST_THROW; 00142 //! Retrieves the item at the given index. An index beyond the end probably causes an exception. 00143 T& operator [] (const uint32_t index) const XSENS_LIST_THROW; 00144 //! Inserts an item at the given index, shifting any items below it down one spot. 00145 void insert(const T& item, const uint32_t index); 00146 //! Inserts a copy of the referenced item at the given index, shifting any items below it down one spot. 00147 template <typename TB> 00148 void insertCopy(const TB& item, const uint32_t index); 00149 //! Assumes the list is sorted and inserts the item at the appropriate spot. 00150 uint32_t insertSorted(const T& item); 00151 //! Assumes the list is sorted by dereferenced values and inserts the item at the appropriate spot. 00152 uint32_t insertSortedDeref(const T& item); 00153 //! Assumes the list is sorted and inserts a copy of the referenced item at the appropriate spot. 00154 template <typename TB> 00155 uint32_t insertSortedCopy(const TB& item); 00156 //! Returns the number of items currently in the list. 00157 uint32_t length(void) const { return m_count; } 00158 //! Sorts the list in an ascending order, using the T::< operator. 00159 void sortAscending(void); 00160 //! Sorts the list in an ascending order, using the T::< operator on dereferenced list items. 00161 void sortAscendingDeref(void); 00162 //! Sorts the first list in an ascending order, using the T::< operator, the second list will be updated the same way. 00163 template <typename T2> 00164 void twinSortAscending(List<T2>& twin); 00165 //! Finds an item in an unsorted list (walk over all items) using the T::== operator 00166 template <typename TB> 00167 uint32_t find(const TB& item) const; 00168 //! Finds an item in an unsorted list (walk over all items) using the T::== operator on dereferenced list items 00169 template <typename TB> 00170 uint32_t findDeref(const TB& item) const; 00171 //! Finds an item in a sorted list (binary search) using the T::== and T::< operators 00172 template <typename TB> 00173 uint32_t findSorted(const TB& item) const; 00174 //! Finds an item in a sorted list (binary search) using the T::== and T::< operators on dereferenced list items 00175 template <typename TB> 00176 uint32_t findSortedDeref(const TB& item) const; 00177 //! Reverse the order of the list, useful for sorted lists that are read/created in the reverse order 00178 void reverse(void); 00179 //! Removes items from the end of the list. 00180 void removeTail(const uint32_t count) XSENS_LIST_THROW; 00181 void deleteAndRemoveTail(const uint32_t count) XSENS_LIST_THROW; 00182 void freeAndRemoveTail(const uint32_t count) XSENS_LIST_THROW; 00183 00184 //! Type for an equality compare function, should return true when NOT equal 00185 typedef int32_t (__cdecl * InequalityFunction)(const T&, const T&); 00186 //! Finds an item in an unsorted list (walk over all items) using the given inequality function 00187 uint32_t find(const T item, InequalityFunction fnc) const; 00188 00189 void deleteItemsOnDestroy(void); 00190 void freeItemsOnDestroy(void); 00191 00192 //! Removes any duplicate entries and returns the number of items removed. Items are compared directly. 00193 uint32_t removeDuplicateEntries(void); 00194 //! Removes any duplicate entries and returns the number of items removed. Items are compared after dereferencing. 00195 uint32_t removeDuplicateEntriesDeref(void); 00196 00197 //! Make a copy of the list, duplicating list items i with: copy[i] = new TB(*source[i]) 00198 template <typename TB> 00199 void isDeepCopyOf(const List<T>& source); 00200 //! Overwrites the current list with a direct copy (a=b) of another list. 00201 void isShallowCopyOf(const List<T>& source); 00202 00203 //! Returns the start of the linear data buffer 00204 const T* getBuffer(void) const { return m_data; } 00205 }; 00206 00207 00208 template <typename T> 00209 List<T>::List() 00210 { 00211 m_max = 16; 00212 m_count = 0; 00213 m_data = (T*) malloc(m_max * sizeof(T)); 00214 m_jcf = NULL; 00215 m_manage = true; 00216 } 00217 00218 template <typename T> 00219 List<T>::List(uint32_t size) 00220 { 00221 m_max = size; 00222 if (m_max == 0) 00223 m_max = 1; 00224 m_count = 0; 00225 m_data = (T*) malloc(m_max * sizeof(T)); 00226 m_jcf = NULL; 00227 m_manage = true; 00228 } 00229 00230 template <typename T> 00231 List<T>::List(const List<T>& src) 00232 { 00233 m_max = src.m_max; 00234 if (m_max == 0) 00235 m_max = 1; 00236 m_count = src.m_count; 00237 m_data = (T*) malloc(m_max * sizeof(T)); 00238 m_jcf = NULL; 00239 if (m_count > 0) 00240 memcpy(m_data,src.m_data,m_count*sizeof(T)); 00241 m_manage = true; 00242 } 00243 00244 template <typename T> 00245 List<T>::List(const uint32_t size, const T* src) 00246 { 00247 m_max = size; 00248 if (m_max == 0) 00249 m_max = 1; 00250 m_count = size; 00251 m_data = (T*) malloc(m_max * sizeof(T)); 00252 m_jcf = NULL; 00253 if (m_count > 0) 00254 memcpy(m_data,src,m_count * sizeof(T)); 00255 m_manage = true; 00256 } 00257 00258 template <typename T> 00259 List<T>::List(const uint32_t size, T* src, bool manage) 00260 { 00261 m_max = size; 00262 m_count = size; 00263 m_data = src; 00264 m_jcf = NULL; 00265 m_manage = manage; 00266 } 00267 00268 template <typename T> 00269 List<T>::~List() 00270 { 00271 if (m_jcf != NULL) 00272 delete m_jcf; 00273 if (m_manage && m_data != NULL) 00274 free(m_data); 00275 m_jcf = NULL; 00276 m_data = NULL; 00277 } 00278 00279 template <typename T> 00280 void List<T>::deleteAndClear(void) 00281 { 00282 for (unsigned i=0;i<m_count;++i) 00283 delete m_data[i]; 00284 m_count = 0; 00285 } 00286 00287 template <typename T> 00288 void List<T>::freeAndClear(void) 00289 { 00290 for (unsigned i=0;i<m_count;++i) 00291 free(m_data[i]); 00292 m_count = 0; 00293 } 00294 00295 template <typename T> 00296 void List<T>::clear(void) 00297 { 00298 m_count = 0; 00299 } 00300 00301 template <typename T> 00302 void List<T>::resize(uint32_t newSize) 00303 { 00304 if (m_manage) 00305 { 00306 if (newSize == m_max) 00307 return; 00308 if (m_count > newSize) 00309 m_max = m_count; 00310 else 00311 m_max = newSize; 00312 if (m_max == 0) 00313 m_max = 1; // size 0 is not allowed 00314 00315 m_data = (T*) realloc(m_data,m_max * sizeof(T)); 00316 } 00317 } 00318 00319 template <typename T> 00320 void List<T>::append(const T& item) 00321 { 00322 if (m_count == m_max) 00323 resize(m_max + 1 + m_max/2); 00324 m_data[m_count++] = item; 00325 } 00326 00327 template <typename T> 00328 void List<T>::appendList(uint32_t count, const T* lst) 00329 { 00330 if (m_count+count > m_max) 00331 resize(m_max + count + m_max/2); 00332 for (unsigned i = 0; i < count; ++i) 00333 m_data[m_count++] = lst[i]; 00334 } 00335 00336 template <typename T> 00337 void List<T>::appendDeepCopy(const List<T>& source) 00338 { 00339 if (m_max < source.m_count + m_count) 00340 resize(source.m_count + m_count); 00341 00342 for (uint32_t i = 0;i<source.m_count;++i) 00343 m_data[m_count++] = new T(*source.m_data[i]); 00344 } 00345 00346 template <typename T> 00347 void List<T>::appendShallowCopy(const List<T>& source) 00348 { 00349 if (m_max < source.m_count + m_count) 00350 resize(source.m_count + m_count); 00351 00352 for (uint32_t i = 0;i<source.m_count;++i) 00353 m_data[m_count++] = source.m_data[i]; 00354 } 00355 00356 template <typename T> 00357 template <typename TB> 00358 void List<T>::appendCopy(const TB& item) 00359 { 00360 if (m_count == m_max) 00361 resize(m_max + 1 + m_max/2); 00362 m_data[m_count++] = new TB(item); 00363 } 00364 00365 template <typename T> 00366 template <typename TR> 00367 void List<T>::appendRelated(const TR& item) 00368 { 00369 if (m_count == m_max) 00370 resize(m_max + 1 + m_max/2); 00371 m_data[m_count++] = item; 00372 } 00373 00374 template <typename T> 00375 T& List<T>::last(void) const XSENS_LIST_THROW 00376 { 00377 #ifdef _XSENS_LIST_RANGE_CHECKS 00378 if (m_count == 0) 00379 throw "List.last: empty list"; 00380 #endif 00381 return m_data[m_count-1]; 00382 } 00383 00384 template <typename T> 00385 T& List<T>::get(const uint32_t index) const XSENS_LIST_THROW 00386 { 00387 #ifdef _XSENS_LIST_RANGE_CHECKS 00388 if (index >= m_count) 00389 throw "List.get: index out of bounds"; 00390 #endif 00391 if (index >= m_count) 00392 return m_data[m_count-1]; 00393 return m_data[index]; 00394 } 00395 00396 template <typename T> 00397 void List<T>::insert(const T& item, const uint32_t index) 00398 { 00399 if (m_count == m_max) 00400 resize(1 + m_max + (m_max >> 1)); 00401 for (unsigned i=m_count;i>index;--i) 00402 m_data[i] = m_data[i-1]; 00403 if (index <= m_count) 00404 m_data[index] = item; 00405 else 00406 m_data[m_count] = item; 00407 m_count++; 00408 } 00409 00410 template <typename T> 00411 template <typename TB> 00412 void List<T>::insertCopy(const TB& item, const uint32_t index) 00413 { 00414 if (m_count == m_max) 00415 resize(1 + m_max + (m_max >> 1)); 00416 for (unsigned i=m_count;i>index;--i) 00417 m_data[i] = m_data[i-1]; 00418 if (index <= m_count) 00419 m_data[index] = new TB(item); 00420 else 00421 m_data[m_count] = new TB(item); 00422 m_count++; 00423 } 00424 00425 template <typename T> 00426 T& List<T>::operator [] (const uint32_t index) const XSENS_LIST_THROW 00427 { 00428 #ifdef _XSENS_LIST_RANGE_CHECKS 00429 if (index >= m_count) 00430 throw "List[]: index out of bounds"; 00431 #endif 00432 return m_data[index]; 00433 } 00434 00435 00436 template <typename T> 00437 void List<T>::qSort(uint32_t left, uint32_t right) 00438 { 00439 uint32_t l_hold, r_hold; 00440 T pivot; 00441 00442 l_hold = left; 00443 r_hold = right; 00444 pivot = m_data[left]; 00445 while (left < right) 00446 { 00447 while (!(m_data[right] < pivot) && (left < right)) 00448 right--; 00449 if (left != right) 00450 { 00451 m_data[left] = m_data[right]; 00452 left++; 00453 } 00454 while (!(pivot < m_data[left]) && (left < right)) 00455 left++; 00456 if (!(left == right)) 00457 { 00458 m_data[right] = m_data[left]; 00459 right--; 00460 } 00461 } 00462 m_data[left] = pivot; 00463 if (l_hold < left) 00464 qSort(l_hold, left-1); 00465 if (r_hold > left) 00466 qSort(left+1, r_hold); 00467 } 00468 00469 template <typename T> 00470 void List<T>::qSortDeref(uint32_t left, uint32_t right) 00471 { 00472 uint32_t l_hold, r_hold; 00473 T pivot; 00474 00475 l_hold = left; 00476 r_hold = right; 00477 pivot = m_data[left]; 00478 while (left < right) 00479 { 00480 while (!(*m_data[right] < *pivot) && (left < right)) 00481 right--; 00482 if (left != right) 00483 { 00484 m_data[left] = m_data[right]; 00485 left++; 00486 } 00487 while (!(*pivot < *m_data[left]) && (left < right)) 00488 left++; 00489 if (!(left == right)) 00490 { 00491 m_data[right] = m_data[left]; 00492 right--; 00493 } 00494 } 00495 m_data[left] = pivot; 00496 if (l_hold < left) 00497 qSortDeref(l_hold, left-1); 00498 if (r_hold > left) 00499 qSortDeref(left+1, r_hold); 00500 } 00501 00502 template <typename T> 00503 void List<T>::sortAscending(void) 00504 { 00505 if (m_count <= 1) 00506 return; 00507 struct Linker { 00508 Linker *prev, *next; 00509 uint32_t index; 00510 00511 T item; 00512 }; 00513 00514 Linker* list = (Linker*) malloc(m_count*sizeof(Linker)); 00515 00516 list[0].prev = NULL; 00517 list[0].next = NULL; 00518 list[0].index = 0; 00519 list[0].item = m_data[0]; 00520 00521 Linker* curr = list; 00522 00523 for (uint32_t i = 1; i < m_count; ++i) 00524 { 00525 list[i].index = i; 00526 list[i].item = m_data[i]; 00527 if (m_data[i] < m_data[curr->index]) 00528 { 00529 while (curr->prev != NULL) 00530 { 00531 curr = curr->prev; 00532 if (!(m_data[i] < m_data[curr->index])) 00533 { 00534 // insert after this 00535 list[i].next = curr->next; 00536 list[i].prev = curr; 00537 curr->next->prev = &list[i]; 00538 curr->next = &list[i]; 00539 curr = &list[i]; 00540 break; 00541 } 00542 } 00543 if (curr != &list[i]) 00544 { 00545 list[i].prev = NULL; 00546 list[i].next = curr; 00547 curr->prev = &list[i]; 00548 curr = &list[i]; 00549 } 00550 } 00551 else 00552 { 00553 while (curr->next != NULL) 00554 { 00555 curr = curr->next; 00556 if (m_data[i] < m_data[curr->index]) 00557 { 00558 // insert before this 00559 list[i].next = curr; 00560 list[i].prev = curr->prev; 00561 curr->prev->next = &list[i]; 00562 curr->prev = &list[i]; 00563 curr = &list[i]; 00564 break; 00565 } 00566 } 00567 if (curr != &list[i]) 00568 { 00569 list[i].prev = curr; 00570 list[i].next = NULL; 00571 curr->next = &list[i]; 00572 curr = &list[i]; 00573 } 00574 } 00575 } 00576 00577 // go to start of list 00578 while (curr->prev != NULL) curr = curr->prev; 00579 00580 // copy sorted list back 00581 for (uint32_t i = 0; i < m_count; ++i) 00582 { 00583 m_data[i] = curr->item; 00584 curr = curr->next; 00585 } 00586 00587 free(list); 00588 } 00589 00590 template <typename T> 00591 void List<T>::sortAscendingDeref(void) 00592 { 00593 if (m_count <= 1) 00594 return; 00595 struct Linker { 00596 Linker *prev, *next; 00597 uint32_t index; 00598 00599 T item; 00600 }; 00601 00602 Linker* list = (Linker*) malloc(m_count*sizeof(Linker)); 00603 00604 list[0].prev = NULL; 00605 list[0].next = NULL; 00606 list[0].index = 0; 00607 list[0].item = m_data[0]; 00608 00609 Linker* curr = list; 00610 00611 for (uint32_t i = 1; i < m_count; ++i) 00612 { 00613 list[i].index = i; 00614 list[i].item = m_data[i]; 00615 if (*m_data[i] < *m_data[curr->index]) 00616 { 00617 while (curr->prev != NULL) 00618 { 00619 curr = curr->prev; 00620 if (!(*m_data[i] < *m_data[curr->index])) 00621 { 00622 // insert after this 00623 list[i].next = curr->next; 00624 list[i].prev = curr; 00625 curr->next->prev = &list[i]; 00626 curr->next = &list[i]; 00627 curr = &list[i]; 00628 break; 00629 } 00630 } 00631 if (curr != &list[i]) 00632 { 00633 list[i].prev = NULL; 00634 list[i].next = curr; 00635 curr->prev = &list[i]; 00636 curr = &list[i]; 00637 } 00638 } 00639 else 00640 { 00641 while (curr->next != NULL) 00642 { 00643 curr = curr->next; 00644 if (*m_data[i] < *m_data[curr->index]) 00645 { 00646 // insert before this 00647 list[i].next = curr; 00648 list[i].prev = curr->prev; 00649 curr->prev->next = &list[i]; 00650 curr->prev = &list[i]; 00651 curr = &list[i]; 00652 break; 00653 } 00654 } 00655 if (curr != &list[i]) 00656 { 00657 list[i].prev = curr; 00658 list[i].next = NULL; 00659 curr->next = &list[i]; 00660 curr = &list[i]; 00661 } 00662 } 00663 } 00664 00665 // go to start of list 00666 while (curr->prev != NULL) curr = curr->prev; 00667 00668 // copy sorted list back 00669 for (uint32_t i = 0; i < m_count; ++i) 00670 { 00671 m_data[i] = curr->item; 00672 curr = curr->next; 00673 } 00674 00675 free(list); 00676 } 00677 00678 template <typename T> 00679 template <typename T2> 00680 void List<T>::twinSortAscending(List<T2>& twin) 00681 { 00682 if (m_count <= 1) 00683 return; 00684 00685 #ifdef _XSENS_LIST_RANGE_CHECKS 00686 if (m_count != twin.m_count) 00687 throw "List.twinSortAscending: sizes do not match"; 00688 #endif 00689 uint32_t iteration = 0; 00690 uint32_t mini; 00691 T tmp; 00692 T2 tmp2; 00693 if (m_count > 1) 00694 while (iteration < m_count-1) 00695 { 00696 mini = iteration; 00697 for (uint32_t i=iteration+1;i<m_count;++i) 00698 { 00699 if (m_data[i] < m_data[mini]) 00700 mini = i; 00701 } 00702 if (mini != iteration) 00703 { 00704 tmp = m_data[mini]; 00705 m_data[mini] = m_data[iteration]; 00706 m_data[iteration] = tmp; 00707 00708 tmp2 = twin.m_data[mini]; 00709 twin.m_data[mini] = twin.m_data[iteration]; 00710 twin.m_data[iteration] = tmp2; 00711 } 00712 ++iteration; 00713 } 00714 } 00715 00716 template <typename T> 00717 void List<T>::remove(const uint32_t index) XSENS_LIST_THROW 00718 { 00719 #ifdef _XSENS_LIST_RANGE_CHECKS 00720 if (index >= m_count) 00721 throw "List.remove: index out of bounds"; 00722 #endif 00723 if (index == m_count-1) 00724 { 00725 --m_count; 00726 return; 00727 } 00728 --m_count; 00729 for (unsigned i = index;i < m_count;++i) 00730 m_data[i] = m_data[i+1]; 00731 } 00732 00733 template <typename T> 00734 void List<T>::removeTail(const uint32_t count) XSENS_LIST_THROW 00735 { 00736 #ifdef _XSENS_LIST_RANGE_CHECKS 00737 if (count > m_count) 00738 throw "List.removeTail: list size less than remove count"; 00739 #endif 00740 if (m_count > count) 00741 { 00742 m_count -= count; 00743 return; 00744 } 00745 m_count = 0; 00746 } 00747 00748 template <typename T> 00749 void List<T>::deleteAndRemoveTail(const uint32_t count) XSENS_LIST_THROW 00750 { 00751 #ifdef _XSENS_LIST_RANGE_CHECKS 00752 if (count > m_count) 00753 throw "List.deleteAndRemoveTail: list size less than remove count"; 00754 #endif 00755 if (m_count > count) 00756 { 00757 for (unsigned i = 0;i < count;++i) 00758 delete m_data[--m_count]; 00759 return; 00760 } 00761 deleteAndClear(); 00762 } 00763 00764 template <typename T> 00765 void List<T>::freeAndRemoveTail(const uint32_t count) XSENS_LIST_THROW 00766 { 00767 #ifdef _XSENS_LIST_RANGE_CHECKS 00768 if (count > m_count) 00769 throw "List.freeAndRemoveTail: list size less than remove count"; 00770 #endif 00771 if (m_count > count) 00772 { 00773 for (unsigned i = 0;i < count;++i) 00774 free(m_data[--m_count]); 00775 return; 00776 } 00777 freeAndClear(); 00778 } 00779 00780 template <typename T> 00781 uint32_t List<T>::removeDuplicateEntries(void) 00782 { 00783 uint32_t removed = 0; 00784 for (uint32_t i=0;i < m_count; ++i) 00785 { 00786 for (uint32_t j=i+1;j < m_count; ++j) 00787 { 00788 if (m_data[i] == m_data[j]) 00789 { 00790 remove(j); 00791 ++removed; 00792 --j; 00793 } 00794 } 00795 } 00796 return removed; 00797 } 00798 00799 template <typename T> 00800 uint32_t List<T>::removeDuplicateEntriesDeref(void) 00801 { 00802 uint32_t removed = 0; 00803 for (uint32_t i=0;i < m_count; ++i) 00804 { 00805 for (uint32_t j=i+1;j < m_count; ++j) 00806 { 00807 if (*(m_data[i]) == *(m_data[j])) 00808 { 00809 remove(j); 00810 ++removed; 00811 --j; 00812 } 00813 } 00814 } 00815 return removed; 00816 } 00817 00818 template <typename T> 00819 void List<T>::deleteAndRemove(const uint32_t index) XSENS_LIST_THROW 00820 { 00821 #ifdef _XSENS_LIST_RANGE_CHECKS 00822 if (index >= m_count) 00823 throw "List.deleteAndRemove: index out of bounds"; 00824 #endif 00825 delete m_data[index]; 00826 if (index == m_count-1) 00827 { 00828 --m_count; 00829 return; 00830 } 00831 --m_count; 00832 for (unsigned i = index;i < m_count;++i) 00833 m_data[i] = m_data[i+1]; 00834 } 00835 00836 template <typename T> 00837 void List<T>::freeAndRemove(const uint32_t index) XSENS_LIST_THROW 00838 { 00839 #ifdef _XSENS_LIST_RANGE_CHECKS 00840 if (index >= m_count) 00841 throw "List.freeAndRemove: index out of bounds"; 00842 #endif 00843 free(m_data[index]); 00844 if (index == m_count-1) 00845 { 00846 --m_count; 00847 return; 00848 } 00849 --m_count; 00850 for (unsigned i = index;i < m_count;++i) 00851 m_data[i] = m_data[i+1]; 00852 } 00853 00854 template <typename T> 00855 template <typename TB> 00856 uint32_t List<T>::find(const TB& item) const 00857 { 00858 for (uint32_t i=0;i<m_count;++i) 00859 if (((const T*)m_data)[i] == item) 00860 return i; 00861 return XSENS_LIST_NOTFOUND; 00862 } 00863 00864 template <typename T> 00865 uint32_t List<T>::find(const T item, InequalityFunction fnc) const 00866 { 00867 for (uint32_t i=0;i<m_count;++i) 00868 if (!fnc(m_data[i],item)) 00869 return i; 00870 return XSENS_LIST_NOTFOUND; 00871 } 00872 00873 template <typename T> 00874 template <typename TB> 00875 uint32_t List<T>::findDeref(const TB& item) const 00876 { 00877 for (uint32_t i=0;i<m_count;++i) 00878 if (*(m_data[i]) == item) 00879 return i; 00880 return XSENS_LIST_NOTFOUND; 00881 } 00882 00883 template <typename T> 00884 template <typename TB> 00885 uint32_t List<T>::findSorted(const TB& item) const 00886 { 00887 if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD) // for small lists, it is faster to simply walk the list 00888 return find(item); 00889 00890 uint32_t x = m_count; 00891 uint32_t n = 1; 00892 uint32_t i; 00893 00894 while(x >= n) 00895 { 00896 i = (x + n) >> 1; 00897 00898 if (m_data[i-1] == item) 00899 return i-1; 00900 if (m_data[i-1] < item) 00901 n = i+1; 00902 else 00903 x = i-1; 00904 } 00905 return XSENS_LIST_NOTFOUND; 00906 } 00907 00908 template <typename T> 00909 template <typename TB> 00910 uint32_t List<T>::findSortedDeref(const TB& item) const 00911 { 00912 if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD) // for small lists, it is faster to simply walk the list 00913 return findDeref(item); 00914 00915 uint32_t x = m_count; 00916 uint32_t n = 1; 00917 uint32_t i; 00918 00919 while(x >= n) 00920 { 00921 i = (x + n) >> 1; 00922 00923 if (*(m_data[i-1]) == item) 00924 return i-1; 00925 if (*(m_data[i-1]) < item) 00926 n = i+1; 00927 else 00928 x = i-1; 00929 } 00930 return XSENS_LIST_NOTFOUND; 00931 } 00932 00933 template <typename T> 00934 uint32_t List<T>::insertSorted(const T& item) 00935 { 00936 uint32_t i; 00937 if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD) 00938 { 00939 for (i=0;i<m_count;++i) 00940 if (item < m_data[i]) 00941 { 00942 insert(item,i); 00943 return i; 00944 } 00945 append(item); 00946 return m_count-1; 00947 } 00948 else 00949 { 00950 uint32_t x = m_count; 00951 uint32_t n = 1; 00952 00953 while(x >= n) 00954 { 00955 i = (x + n) >> 1; 00956 00957 if (m_data[i-1] == item) 00958 { 00959 insert(item,i-1); 00960 return i-1; 00961 } 00962 if (m_data[i-1] < item) 00963 n = i+1; 00964 else 00965 x = i-1; 00966 } 00967 insert(item,n-1); 00968 return n-1; 00969 } 00970 } 00971 00972 template <typename T> 00973 uint32_t List<T>::insertSortedDeref(const T& item) 00974 { 00975 uint32_t i; 00976 if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD) 00977 { 00978 for (i=0;i<m_count;++i) 00979 if (*item < *m_data[i]) 00980 { 00981 insert(item,i); 00982 return i; 00983 } 00984 append(item); 00985 return m_count-1; 00986 } 00987 else 00988 { 00989 uint32_t x = m_count; 00990 uint32_t n = 1; 00991 00992 while(x >= n) 00993 { 00994 i = (x + n) >> 1; 00995 00996 if (*(m_data[i-1]) == *item) 00997 { 00998 insert(item,i-1); 00999 return i-1; 01000 } 01001 if (*(m_data[i-1]) < *item) 01002 n = i+1; 01003 else 01004 x = i-1; 01005 } 01006 insert(item,n-1); 01007 return n-1; 01008 } 01009 } 01010 01011 template <typename T> 01012 template <typename TB> 01013 uint32_t List<T>::insertSortedCopy(const TB& item) 01014 { 01015 uint32_t i; 01016 if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD) 01017 { 01018 for (i=0;i<m_count;++i) 01019 if (item < m_data[i]) 01020 { 01021 insertCopy<TB>(item,i); 01022 return i; 01023 } 01024 append(item); 01025 return m_count-1; 01026 } 01027 else 01028 { 01029 uint32_t x = m_count; 01030 uint32_t n = 1; 01031 01032 while(x >= n) 01033 { 01034 i = (x + n) >> 1; 01035 01036 if (m_data[i-1] == item) 01037 { 01038 insertCopy<TB>(item,i-1); 01039 return i-1; 01040 } 01041 if (m_data[i-1] < item) 01042 n = i+1; 01043 else 01044 x = i-1; 01045 } 01046 insertCopy<TB>(item,n-1); 01047 return n-1; 01048 } 01049 } 01050 01051 template <typename T> 01052 void List<T>::deleteItemsOnDestroy(void) 01053 { 01054 if (m_jcf != NULL) 01055 { 01056 m_jcf->disable(); 01057 delete m_jcf; 01058 } 01059 m_jcf = new JanitorClassFunc<List<T>, void>(*this,&List<T>::deleteAndClear); 01060 } 01061 01062 template <typename T> 01063 void List<T>::freeItemsOnDestroy(void) 01064 { 01065 if (m_jcf != NULL) 01066 { 01067 m_jcf->disable(); 01068 delete m_jcf; 01069 } 01070 m_jcf = new JanitorClassFunc<List<T>, void>(*this,&List<T>::freeAndClear); 01071 } 01072 01073 template <typename T> 01074 template <typename TB> 01075 void List<T>::isDeepCopyOf(const List<T>& source) 01076 { 01077 m_count = 0; 01078 if (m_max < source.m_count) 01079 resize(source.m_count); 01080 m_count = source.m_count; 01081 for (uint32_t i = 0;i<m_count;++i) 01082 m_data[i] = new TB(*source.m_data[i]); 01083 } 01084 01085 template <typename T> 01086 void List<T>::isShallowCopyOf(const List<T>& x) 01087 { 01088 m_count = 0; 01089 if (m_max < x.m_count) 01090 resize(x.m_count); 01091 m_count = x.m_count; 01092 for (uint32_t i = 0;i<m_count;++i) 01093 m_data[i] = x.m_data[i]; 01094 } 01095 01096 template <typename T> 01097 void List<T>::swap(const uint32_t i, const uint32_t j) XSENS_LIST_THROW 01098 { 01099 #ifdef _XSENS_LIST_RANGE_CHECKS 01100 if (i >= m_count || j >= m_count) 01101 throw "List.swap: index out of bounds"; 01102 #endif 01103 T tmp = m_data[i]; 01104 m_data[i] = m_data[j]; 01105 m_data[j] = tmp; 01106 } 01107 01108 template <typename T> 01109 void List<T>::reverse(void) 01110 { 01111 uint32_t half = m_count / 2; 01112 for (uint32_t i = 0, end=m_count-1; i < half; ++i,--end) 01113 { 01114 T tmp = m_data[i]; 01115 m_data[i] = m_data[end]; 01116 m_data[end] = tmp; 01117 } 01118 } 01119 01120 } // end of xsens namespace 01121 01122 #endif // _XSENS_LIST_H_2006_06_08