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

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