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.

Map.h 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /*!
  2. * \file include/Map.h
  3. * \brief Template Map
  4. *
  5. * Using RBTree and list overlay for faster access
  6. *
  7. * Access: O(1)/O(n)/O(logn) ?
  8. * Insert: O(nlogn) ?
  9. * Remove: O(nlogn) ?
  10. *
  11. * \author Mongoose
  12. * \author xythobuz
  13. */
  14. #ifndef _MAP_H_
  15. #define _MAP_H_
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <Tree.h>
  19. #ifdef DEBUG_MEMORY
  20. #include <memory_test.h>
  21. #endif
  22. /*!
  23. * \brief Template class encapsulating a single map node
  24. * \tparam K key type
  25. * \tparam D data type
  26. */
  27. template <class K, class D> class MapNode {
  28. public:
  29. /*!
  30. * \brief Construct a MapNode
  31. * \param key key of this Node
  32. * \param data data of this Node
  33. */
  34. MapNode(K key, D data) {
  35. _data = data;
  36. _key = key;
  37. _next = NULL;
  38. }
  39. /*!
  40. * \brief Deconstruct a MapNode
  41. */
  42. ~MapNode() {
  43. }
  44. /*!
  45. * \brief Set the key of this MapNode
  46. * \param key new key
  47. */
  48. void Key(K key) {
  49. _key = key;
  50. }
  51. /*!
  52. * \brief Get the key of this MapNode
  53. * \returns key
  54. */
  55. K Key() {
  56. return _key;
  57. }
  58. /*!
  59. * \brief Set the data of this MapNode
  60. * \param data new data
  61. */
  62. void Data(D data) {
  63. _data = data;
  64. }
  65. /*!
  66. * \brief Get the data of this MapNode
  67. * \returns data
  68. */
  69. D Data() {
  70. return _data;
  71. }
  72. /*!
  73. * \brief Get the next MapNode in the Map
  74. * \returns next pointer
  75. */
  76. MapNode<K, D> *Next() {
  77. return _next;
  78. }
  79. /*!
  80. * \brief Set the next MapNode in the Map
  81. * \param next new next pointer
  82. */
  83. void Next(MapNode<K, D> *next) {
  84. _next = next;
  85. }
  86. private:
  87. MapNode<K, D> *_next; //!< Next pointer
  88. K _key; //!< Key of the MapNode
  89. D _data; //!< Data of the MapNode
  90. };
  91. /*!
  92. * \brief Template class representing a Map, mapping data to a key.
  93. * \tparam K key type
  94. * \tparam D data type
  95. */
  96. template <class K, class D> class Map {
  97. public:
  98. /*!
  99. * \brief Construct a Map
  100. */
  101. Map() {
  102. UnSetError();
  103. _num_items = 0;
  104. _head = NULL;
  105. _current = NULL;
  106. _cache = NULL;
  107. }
  108. /*!
  109. * \brief Deconstruct a Map
  110. * \sa Map::Clear()
  111. */
  112. ~Map() {
  113. Clear();
  114. }
  115. /*!
  116. * \brief Deletes every item in the Map. Clears error flag.
  117. */
  118. void Clear() {
  119. UnSetError();
  120. _num_items = 0;
  121. _cache = NULL;
  122. while (_head) {
  123. _current = _head;
  124. _head = _head->Next();
  125. delete _current;
  126. }
  127. _tree.Clear();
  128. }
  129. /*!
  130. * \brief Set the error flag
  131. */
  132. void SetError() {
  133. _error = true;
  134. }
  135. /*!
  136. * \brief Unset the error flag
  137. */
  138. void UnSetError() {
  139. _error = false;
  140. }
  141. /*!
  142. * \brief Get the error flag
  143. * \returns error flag
  144. */
  145. bool GetError() {
  146. return _error;
  147. }
  148. /*!
  149. * \brief Search for data with a key. Sets error flag if nothing is found.
  150. * \param key key to search for
  151. * \returns data matching key or 0
  152. */
  153. D FindDataByKey(K key) {
  154. MapNode<K, D> *current = NULL;
  155. MapNode<K, D> *next = NULL;
  156. if (_head) {
  157. UnSetError();
  158. if (_cache) {
  159. next = _cache->Next();
  160. }
  161. // Mongoose 2002.02.19, Optimize for sequential searches
  162. if (next && key == next->Key()) {
  163. current = next;
  164. } else { // Mongoose 2002.02.19, Use search algorithm otherwise
  165. current = _tree.SearchByKey(key, &_error);
  166. if (_error)
  167. return false;
  168. }
  169. if (current) {
  170. _cache = _current = current;
  171. return current->Data();
  172. }
  173. }
  174. SetError();
  175. return 0;
  176. }
  177. /*!
  178. * \brief Search for data with a key
  179. * \param key key to search for
  180. * \returns data matching key or 0
  181. * \sa Map::FindDataByKey()
  182. */
  183. D operator [] (K key) {
  184. return FindDataByKey(key);
  185. }
  186. /*!
  187. * \brief Search for a key with specific data. Sets error flag if nothing is found.
  188. * \param data data to search for
  189. * \returns key matching data or 0
  190. */
  191. K FindKeyByData(D data) {
  192. MapNode<K, D> *current = _head;
  193. MapNode<K, D> *last = NULL;
  194. UnSetError();
  195. while (current) {
  196. // Found
  197. if (current->Data() == data) {
  198. _cache = current;
  199. return current->Key();
  200. }
  201. last = current;
  202. current = current->Next();
  203. }
  204. SetError();
  205. return 0;
  206. }
  207. /*!
  208. * \brief Returns data of the cached MapNode
  209. * \returns cached data
  210. */
  211. D getCache() {
  212. if (_cache == 0x0) {
  213. printf("Map::getCache> Bad request - should segfault\n");
  214. }
  215. return _cache->Data();
  216. }
  217. /*!
  218. * \brief Check if a key is in this map. Sets error flag if nothing is found.
  219. * \returns true if the key is in the map, false otherwise
  220. * \sa Tree:SearchByKey()
  221. */
  222. bool findKey(K key) {
  223. MapNode<K, D> *current = NULL;
  224. MapNode<K, D> *next = NULL;
  225. if (_head) {
  226. UnSetError();
  227. if (_cache) {
  228. if (_cache->Key() == key) {
  229. return true;
  230. }
  231. next = _cache->Next();
  232. }
  233. // Mongoose 2002.02.19, Optimize for sequential searches
  234. if (next && key == next->Key()) {
  235. current = next;
  236. } else { // Mongoose 2002.02.19, Use search algorithm otherwise
  237. current = _tree.SearchByKey(key, &_error);
  238. }
  239. if (current) {
  240. _cache = _current = current;
  241. //curData = current->Data();
  242. return true;
  243. }
  244. }
  245. SetError();
  246. return false;
  247. }
  248. /*!
  249. * \brief Add a Key-Data pair to the Map, creating a new MapNode. Clears error flag.
  250. * \param key key to add
  251. * \param data to add
  252. * \returns true on success, false if there is not enough memory
  253. */
  254. bool Add(K key, D data) {
  255. MapNode<K, D> *node;
  256. UnSetError();
  257. node = new MapNode<K, D>(key, data);
  258. _num_items++;
  259. return Add(node);
  260. }
  261. /*!
  262. * \brief Add a MapNode to the Map. Clears error flag on success.
  263. * \param node node to add
  264. * \returns true on success, false if node is NULL
  265. * \sa Tree:Insert()
  266. */
  267. bool Add(MapNode<K, D> *node) {
  268. MapNode<K, D> *current = _head;
  269. MapNode<K, D> *last = NULL;
  270. if (!node)
  271. return false;
  272. UnSetError();
  273. if (_head) {
  274. current = _head;
  275. last = NULL;
  276. while (current) {
  277. // Prepend
  278. if (current->Key() > node->Key()) {
  279. node->Next(current);
  280. if (current == _head) {
  281. _head = node;
  282. } else if (last) {
  283. last->Next(node);
  284. }
  285. _tree.Insert(node->Key(), node);
  286. return true;
  287. }
  288. last = current;
  289. current = current->Next();
  290. }
  291. // Append
  292. last->Next(node);
  293. } else {
  294. _head = node;
  295. }
  296. _tree.Insert(node->Key(), node);
  297. return true;
  298. }
  299. /*!
  300. * \brief Remove item with the specified key. Sets error flag if nothing is removed.
  301. * \param key key to remove
  302. */
  303. void RemoveByKey(K key) {
  304. MapNode<K, D> *current = _head;
  305. MapNode<K, D> *last = NULL;
  306. UnSetError();
  307. _cache = NULL;
  308. while (current) {
  309. // Remove
  310. if (current->Key() == key) {
  311. if (current == _head) {
  312. _head = current->Next();
  313. } else {
  314. last->Next(current->Next());
  315. }
  316. if (_current == current) {
  317. _current = NULL;
  318. }
  319. _tree.RemoveByKey(current->Key());
  320. delete current;
  321. _num_items--;
  322. return;
  323. }
  324. last = current;
  325. current = current->Next();
  326. }
  327. SetError();
  328. }
  329. /*!
  330. * \brief Remove item with the specified data. Sets error flag if nothing is removed.
  331. * \param data data to remove
  332. */
  333. void RemoveByData(D data) {
  334. MapNode<K, D> *current = _head;
  335. MapNode<K, D> *last = NULL;
  336. UnSetError();
  337. _cache = NULL;
  338. while (current)
  339. {
  340. // Remove
  341. if (current->Data() == data) {
  342. if (current == _head) {
  343. _head = current->Next();
  344. } else {
  345. last->Next(current->Next());
  346. }
  347. if (_current == current) {
  348. _current = NULL;
  349. }
  350. _tree.RemoveByKey(current->Key());
  351. delete current;
  352. _num_items--;
  353. return;
  354. }
  355. last = current;
  356. current = current->Next();
  357. }
  358. SetError();
  359. }
  360. /*!
  361. * \brief Check if the Map is empty
  362. * \returns true if Map is empty, false otherwise
  363. */
  364. bool Empty() {
  365. return (_head == NULL);
  366. }
  367. /*!
  368. * \brief Returns number of items in the Map
  369. * \returns number of items
  370. */
  371. unsigned int NumItems() {
  372. return _num_items;
  373. }
  374. /*!
  375. * \brief Print the Map. Sets error flag if one or both functions aren't provided.
  376. * \param print_key_func function that prints a key
  377. * \param print_data_func function that prints the data
  378. */
  379. void Print(void (*print_key_func)(K), void (*print_data_func)(D)) {
  380. MapNode<K, D> *current = _head;
  381. UnSetError();
  382. if (!print_key_func || !print_data_func) {
  383. SetError();
  384. return;
  385. }
  386. printf(" [%i] {\n", _num_items);
  387. while (current) {
  388. printf("(");
  389. (*print_key_func)(current->Key());
  390. printf(", ");
  391. (*print_data_func)(current->Data());
  392. printf("), ");
  393. current = current->Next();
  394. fflush(stdout);
  395. }
  396. printf(" }\n");
  397. }
  398. /*!
  399. * \brief Reset the Map iterator
  400. */
  401. void Reset() {
  402. _current = _head;
  403. _cache = _head;
  404. }
  405. /*!
  406. * \brief Iterate over the Map
  407. * \returns true if there is a new current element
  408. * \sa Map::Next()
  409. */
  410. bool operator ++ (int) {
  411. return Next();
  412. }
  413. /*!
  414. * \brief Iterate over the Map
  415. * \returns true if there is a new current element
  416. * \sa Map::Next()
  417. */
  418. bool operator ++ () {
  419. return Next();
  420. }
  421. /*!
  422. * \brief Iterate over the Map
  423. * \returns true if there is a new current element
  424. * \sa Map::Next()
  425. */
  426. bool Next() {
  427. if (_current) {
  428. _current = _current->Next();
  429. }
  430. return (_current != NULL);
  431. }
  432. /*!
  433. * \brief Check if there is a current item in the iterator
  434. * \returns true if the current item exists
  435. */
  436. bool CurrentExists() {
  437. return (_current != 0);
  438. }
  439. /*!
  440. * \brief Returns the key of the current item. Sets error flag if there is no current item.
  441. * \returns key or 0 if there is no current item
  442. */
  443. K CurrentKey() {
  444. UnSetError();
  445. if (!_current) {
  446. SetError();
  447. return 0;
  448. }
  449. return _current->Key();
  450. }
  451. /*!
  452. * \brief Returns the data of the current item. Sets error flag if there is no current item.
  453. * \returns data or 0 if there is no current item
  454. */
  455. D Current() {
  456. UnSetError();
  457. if (!_current) {
  458. SetError();
  459. return 0;
  460. }
  461. return _current->Data();
  462. }
  463. private:
  464. unsigned int _num_items; //!< Number of items in the Map
  465. bool _error; //!< Error flag
  466. Tree<K, MapNode<K, D> *> _tree; //!< Tree containing the MapNodes
  467. MapNode<K, D> *_head; //!< First item of the Map
  468. MapNode<K, D> *_current; //!< Current item for the iterator
  469. MapNode<K, D> *_cache; //!< Cached item used by search & remove methods
  470. };
  471. #endif