Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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("(%i, %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[%i] = 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(" [%i] {\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 %i {\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