Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

List.h 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*!
  2. * \file include/List.h
  3. * \brief Template list
  4. *
  5. * UINT_MAX is an error condition, used in place of -1
  6. *
  7. * \author Mongoose
  8. * \author xythobuz
  9. */
  10. #ifndef _LIST_H_
  11. #define _LIST_H_
  12. #include <stdlib.h>
  13. #include <limits.h>
  14. #include <stdio.h>
  15. #ifdef DEBUG_MEMORY
  16. #include <memory_test.h>
  17. #endif
  18. /*!
  19. * \brief Template class encapsulating a single list node
  20. * \tparam T encapsulated data type
  21. */
  22. template <class T> class ListNode {
  23. public:
  24. /*!
  25. * \brief Create a new ListNode
  26. * \param data Data to be stored in node
  27. * \param id node id
  28. */
  29. ListNode(T data, unsigned int id) {
  30. _data = data;
  31. _id = id;
  32. _next = NULL;
  33. }
  34. /*!
  35. * \brief Destroy a ListNode
  36. */
  37. ~ListNode() {
  38. }
  39. /*!
  40. * \brief Set the id of this ListNode
  41. * \param id new id
  42. */
  43. void Id(unsigned int id) {
  44. _id = id;
  45. }
  46. /*!
  47. * \brief Get the id of this ListNode
  48. * \returns current id
  49. */
  50. unsigned int Id() {
  51. return _id;
  52. }
  53. /*!
  54. * \brief Set the data of this ListNode
  55. * \param data new data
  56. */
  57. void Data(T data) {
  58. _data = data;
  59. }
  60. /*!
  61. * \brief Get the data of this ListNode
  62. * \returns current data
  63. */
  64. T Data() {
  65. return _data;
  66. }
  67. /*!
  68. * \brief Get the next ListNode in the List
  69. * \returns next pointer or NULL
  70. */
  71. ListNode<T> *Next() {
  72. return _next;
  73. }
  74. /*!
  75. * \brief Set the next ListNode in the List
  76. * \param next new next pointer
  77. */
  78. void Next(ListNode<T> *next) {
  79. _next = next;
  80. }
  81. /*!
  82. * \brief Print this ListNode
  83. */
  84. void Print() {
  85. printf("(%u, %p)", _id, _data);
  86. }
  87. private:
  88. ListNode<T> *_next; //!< Next Pointer
  89. unsigned int _id; //!< ListNode ID
  90. T _data; //!< Encapsulated data
  91. };
  92. /*!
  93. * \brief Template class representing a linked list
  94. * \tparam T encapsulated data type
  95. */
  96. template <class T> class List {
  97. public:
  98. /*!
  99. * \brief Construct a new linked list
  100. */
  101. List() {
  102. _num_items = 0;
  103. _head = NULL;
  104. _current = NULL;
  105. _last = NULL;
  106. _cache = NULL;
  107. }
  108. /*!
  109. * \brief Deconstruct a linked list
  110. * \sa List::Clear()
  111. */
  112. ~List() {
  113. Clear();
  114. }
  115. /*!
  116. * \brief Add all data from another list to this one
  117. * NOTE: this only copies data, the containers aren't the same ids
  118. * \param list source list where data does come from
  119. */
  120. void Copy(List<T> *list) {
  121. if (!list)
  122. return;
  123. for (list->Reset(); list->CurrentExists(); list->Next())
  124. Add(list->Current());
  125. }
  126. /*!
  127. * \brief Delete every item in this list
  128. */
  129. void Clear() {
  130. _num_items = 0;
  131. _last = _cache = NULL;
  132. while (_head) {
  133. _current = _head;
  134. _head = _head->Next();
  135. delete _current;
  136. }
  137. }
  138. /*!
  139. * \brief Searches the list for an id
  140. * \param id id to be searched
  141. * \returns data with id, or 0
  142. */
  143. T SearchId(unsigned int id) {
  144. ListNode<T> *current = _head;
  145. ListNode<T> *last = NULL;
  146. if (_cache) {
  147. if (id >= _cache->Id())
  148. current = _cache;
  149. }
  150. while (current) {
  151. // Found
  152. if (current->Id() == id) {
  153. _cache = current;
  154. return current->Data();
  155. }
  156. last = current;
  157. current = current->Next();
  158. }
  159. return 0;
  160. }
  161. /*!
  162. * \brief Searches the list for specific data
  163. * \param data data to be searched for
  164. * \returns id of data, or UINT_MAX
  165. */
  166. unsigned int SearchKey(T data) {
  167. ListNode<T> *current = _head;
  168. ListNode<T> *last = NULL;
  169. if (_cache) {
  170. // Mongoose: 2001-01-31, hhmmm... fixed?
  171. if (data == _cache->Data())
  172. return _cache->Id();
  173. }
  174. while (current) {
  175. // Found
  176. if (current->Data() == data) {
  177. _cache = current;
  178. return current->Id();
  179. }
  180. last = current;
  181. current = current->Next();
  182. }
  183. return UINT_MAX;
  184. }
  185. /*!
  186. * \brief Search for an id
  187. * \param i id to be searched
  188. * \returns id or 0
  189. * \sa List::SearchId()
  190. */
  191. T operator [] (unsigned int i) {
  192. if (_head) {
  193. return SearchId(i);
  194. } else {
  195. #ifdef DEBUG_INDEX_EMPTY_LIST
  196. printf("List[%u] = NULL\n", i);
  197. #endif
  198. }
  199. return 0;
  200. }
  201. /*!
  202. * \brief Search for an id and remove the associated item from the list
  203. * \param id id to be deleted
  204. */
  205. void RemoveId(unsigned int id) {
  206. ListNode<T> *current = _head;
  207. ListNode<T> *last = NULL;
  208. _last = _cache = NULL;
  209. while (current) {
  210. // Remove
  211. if (current->Id() == id) {
  212. if (current == _head)
  213. _head = current->Next();
  214. else
  215. last->Next(current->Next());
  216. if (_current == current)
  217. _current = NULL;
  218. delete current;
  219. _num_items--;
  220. return;
  221. }
  222. last = current;
  223. current = current->Next();
  224. }
  225. }
  226. /*!
  227. * \brief Search for data and remove the associated item from the list
  228. * \param data data to be deleted
  229. */
  230. void Remove(T data) {
  231. ListNode<T> *current = _head;
  232. ListNode<T> *last = NULL;
  233. _last = _cache = NULL;
  234. while (current) {
  235. // Remove
  236. if (current->Data() == data) {
  237. if (current == _head)
  238. _head = current->Next();
  239. else
  240. last->Next(current->Next());
  241. if (_current == current)
  242. _current = NULL;
  243. delete current;
  244. _num_items--;
  245. return;
  246. }
  247. last = current;
  248. current = current->Next();
  249. }
  250. }
  251. /*!
  252. * \brief Is the list empty?
  253. * \returns true if the list is empty
  254. */
  255. bool Empty() {
  256. return (_head == NULL);
  257. }
  258. /*!
  259. * \brief Length of the list
  260. * \returns number of items in the list
  261. */
  262. unsigned int NumItems() {
  263. return _num_items;
  264. }
  265. /*!
  266. * \brief Print the list
  267. * \param print_func function that will be called for each item in the list, after its id was printed. Or NULL.
  268. */
  269. void Print(void (*print_func)(T)) {
  270. ListNode<T> *current = _head;
  271. printf(" [%u] {\n", _num_items);
  272. while (current) {
  273. printf("#%i, ", current->Id());
  274. if (print_func)
  275. (*print_func)(current->Data());
  276. current = current->Next();
  277. fflush(stdout);
  278. }
  279. printf(" }\n");
  280. }
  281. /*!
  282. * \brief Print all IDs in this list
  283. */
  284. void Print() {
  285. ListNode<T> *current = _head;
  286. printf("List %u {\n", _num_items);
  287. while (current) {
  288. //current->Print();
  289. printf("%i", current->Id());
  290. current = current->Next();
  291. if (current)
  292. printf(", ");
  293. fflush(stdout);
  294. }
  295. printf(" }\n");
  296. }
  297. /*!
  298. * \brief Reset the iterator
  299. */
  300. void Reset() {
  301. _current = _head;
  302. _cache = _head;
  303. }
  304. /*!
  305. * \brief Traverses the list
  306. * \returns true if there is a new current item, false if the list is at the end
  307. * \sa List::Next()
  308. */
  309. bool operator ++ (int) {
  310. return Next();
  311. }
  312. /*!
  313. * \brief Traverses the list
  314. * \returns true if there is a new current item, false if the list is at the end
  315. * \sa List::Next()
  316. */
  317. bool operator ++ () {
  318. return Next();
  319. }
  320. /*!
  321. * \brief Traverses the list
  322. * \returns true if there is a new current item, false if the list is at the end
  323. */
  324. bool Next() {
  325. if (_current)
  326. _current = _current->Next();
  327. return (_current != NULL);
  328. }
  329. /*!
  330. * \brief Get the id of the current item
  331. * \returns id of current item or UINT_MAX if there is no current item
  332. */
  333. unsigned int CurrentId() {
  334. if (!_current)
  335. return UINT_MAX;
  336. return _current->Id();
  337. }
  338. /*!
  339. * \brief Is there a current item?
  340. * \returns true if there is a current item, false otherwise
  341. */
  342. bool CurrentExists() {
  343. return (_current != 0);
  344. }
  345. /*!
  346. * \brief Get the current items data
  347. * \returns data of the current item or 0 if there is no current item
  348. */
  349. T Current() {
  350. if (_current)
  351. return _current->Data();
  352. else
  353. return 0;
  354. }
  355. /*!
  356. * \brief Add data to the list. Constructs a new ListNode encapsulating the data.
  357. * \param data data to be stored
  358. * \returns id of the new ListNode
  359. */
  360. unsigned int Add(T data) {
  361. ListNode<T> *node;
  362. node = new ListNode<T>(data, _num_items++);
  363. return Add(node);
  364. }
  365. /*!
  366. * \brief Add a ListNode to the end of this List.
  367. * \param node new node
  368. * \returns id of the node
  369. */
  370. unsigned int Add(ListNode<T> *node) {
  371. ListNode<T> *current;
  372. ListNode<T> *last;
  373. unsigned int i;
  374. if (_head) {
  375. current = _head;
  376. last = NULL;
  377. i = 0;
  378. //EXP
  379. if (_last) {
  380. i = _last->Id();
  381. current = _last;
  382. }
  383. while (current) {
  384. // Prepend
  385. if (current->Id() > i) {
  386. node->Id(i);
  387. node->Next(current);
  388. if (current == _head)
  389. _head = node;
  390. else if (last)
  391. last->Next(node);
  392. return node->Id();
  393. }
  394. i++;
  395. last = current;
  396. current = current->Next();
  397. }
  398. // Append
  399. last->Next(node);
  400. } else
  401. _head = node;
  402. _last = node; //EXP
  403. return node->Id();
  404. }
  405. private:
  406. unsigned int _num_items; //!< Number of items in the list
  407. ListNode<T> *_head; //!< First item in the list
  408. ListNode<T> *_current; //!< Current item for the list iterator
  409. ListNode<T> *_last; //!< Last item in the list
  410. ListNode<T> *_cache; //!< cache used by the search methods
  411. };
  412. #endif