LinkedList2.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /**
  2. * @file LinkedList2.h
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. * @section DESCRIPTION
  23. *
  24. * Doubly linked list that support multiple iterations and removing
  25. * aritrary elements during iteration.
  26. */
  27. #ifndef BADVPN_STRUCTURE_LINKEDLIST2_H
  28. #define BADVPN_STRUCTURE_LINKEDLIST2_H
  29. #include <stddef.h>
  30. #include <stdint.h>
  31. #include <misc/debug.h>
  32. struct LinkedList2Iterator_t;
  33. /**
  34. * Linked list node.
  35. */
  36. typedef struct LinkedList2Node_t
  37. {
  38. struct LinkedList2Node_t *p;
  39. struct LinkedList2Node_t *n;
  40. struct LinkedList2Iterator_t *it;
  41. } LinkedList2Node;
  42. /**
  43. * Doubly linked list that support multiple iterations and removing
  44. * aritrary elements during iteration.
  45. */
  46. typedef struct
  47. {
  48. LinkedList2Node *first;
  49. LinkedList2Node *last;
  50. } LinkedList2;
  51. /**
  52. * Linked list iterator.
  53. */
  54. typedef struct LinkedList2Iterator_t
  55. {
  56. LinkedList2 *list;
  57. int8_t dir;
  58. struct LinkedList2Node_t *e;
  59. struct LinkedList2Iterator_t *pi;
  60. struct LinkedList2Iterator_t *ni;
  61. } LinkedList2Iterator;
  62. /**
  63. * Initializes the linked list.
  64. *
  65. * @param list list to initialize
  66. */
  67. static void LinkedList2_Init (LinkedList2 *list);
  68. /**
  69. * Determines if the list is empty.
  70. *
  71. * @param list the list
  72. * @return 1 if empty, 0 if not
  73. */
  74. static int LinkedList2_IsEmpty (LinkedList2 *list);
  75. /**
  76. * Returns the first node of the list.
  77. *
  78. * @param list the list
  79. * @return first node of the list, or NULL if the list is empty
  80. */
  81. static LinkedList2Node * LinkedList2_GetFirst (LinkedList2 *list);
  82. /**
  83. * Returns the last node of the list.
  84. *
  85. * @param list the list
  86. * @return last node of the list, or NULL if the list is empty
  87. */
  88. static LinkedList2Node * LinkedList2_GetLast (LinkedList2 *list);
  89. /**
  90. * Inserts a node to the beginning of the list.
  91. *
  92. * @param list the list
  93. * @param node uninitialized node to insert
  94. */
  95. static void LinkedList2_Prepend (LinkedList2 *list, LinkedList2Node *node);
  96. /**
  97. * Inserts a node to the end of the list.
  98. *
  99. * @param list the list
  100. * @param node uninitialized node to insert
  101. */
  102. static void LinkedList2_Append (LinkedList2 *list, LinkedList2Node *node);
  103. /**
  104. * Inserts a node before a given node.
  105. *
  106. * @param list the list
  107. * @param node uninitialized node to insert
  108. * @param target node in the list to insert before
  109. */
  110. static void LinkedList2_InsertBefore (LinkedList2 *list, LinkedList2Node *node, LinkedList2Node *target);
  111. /**
  112. * Inserts a node after a given node.
  113. *
  114. * @param list the list
  115. * @param node uninitialized node to insert
  116. * @param target node in the list to insert after
  117. */
  118. static void LinkedList2_InsertAfter (LinkedList2 *list, LinkedList2Node *node, LinkedList2Node *target);
  119. /**
  120. * Removes a node from the list.
  121. *
  122. * @param list the list
  123. * @param node node to remove
  124. */
  125. static void LinkedList2_Remove (LinkedList2 *list, LinkedList2Node *node);
  126. /**
  127. * Returns the next node of a given node.
  128. *
  129. * @param node reference node
  130. * @return next node, or NULL if none
  131. */
  132. static LinkedList2Node * LinkedList2Node_Next (LinkedList2Node *node);
  133. /**
  134. * Returns the previous node of a given node.
  135. *
  136. * @param node reference node
  137. * @return previous node, or NULL if none
  138. */
  139. static LinkedList2Node * LinkedList2Node_Prev (LinkedList2Node *node);
  140. /**
  141. * Initializes a linked list iterator.
  142. * The iterator memory must remain available until either of these occurs:
  143. * - the list is no longer needed, or
  144. * - the iterator is freed with {@link LinkedList2Iterator_Free}, or
  145. * - the iterator reaches the end of iteration.
  146. *
  147. * @param it uninitialized iterator to initialize
  148. * @param list the list
  149. * @param dir direction of iteration. Must be 1 (forward) or -1 (backward).
  150. * @param node current position of the iterator. Can be a node in the list
  151. * or NULL for end of iteration.
  152. */
  153. static void LinkedList2Iterator_Init (LinkedList2Iterator *it, LinkedList2 *list, int dir, LinkedList2Node *node);
  154. /**
  155. * Frees a linked list iterator.
  156. *
  157. * @param it iterator to free
  158. */
  159. static void LinkedList2Iterator_Free (LinkedList2Iterator *it);
  160. /**
  161. * Initializes a linked list iterator with forward direction, with the current
  162. * position at the first node (or at the end of iteration if there are no nodes).
  163. * The iterator memory must remain available until either of these occurs:
  164. * - the list is no longer needed, or
  165. * - the iterator is freed with {@link LinkedList2Iterator_Free}, or
  166. * - the iterator reaches the end of iteration.
  167. *
  168. * @param it uninitialized iterator to initialize
  169. * @param list the list
  170. */
  171. static void LinkedList2Iterator_InitForward (LinkedList2Iterator *it, LinkedList2 *list);
  172. /**
  173. * Initializes a linked list iterator with backward direction, with the current
  174. * position at the last node (or at the end of iteration if there are no nodes).
  175. * The iterator memory must remain available until either of these occurs:
  176. * - the list is no longer needed, or
  177. * - the iterator is freed with {@link LinkedList2Iterator_Free}, or
  178. * - the iterator reaches the end of iteration.
  179. *
  180. * @param it uninitialized iterator to initialize
  181. * @param list the list
  182. */
  183. static void LinkedList2Iterator_InitBackward (LinkedList2Iterator *it, LinkedList2 *list);
  184. /**
  185. * Moves the iterator one node forward or backward (depending on its direction), or,
  186. * if it's at the last or first node (depending on the direction), it reaches
  187. * the end of iteration, or, if it's at the end of iteration, it remains there.
  188. * Returns the the previous position.
  189. *
  190. * @param it the iterator
  191. * @return node on the position of iterator before it was (possibly) moved, or NULL
  192. * if it was at the end of iteration
  193. */
  194. static LinkedList2Node * LinkedList2Iterator_Next (LinkedList2Iterator *it);
  195. void LinkedList2_Init (LinkedList2 *list)
  196. {
  197. list->first = NULL;
  198. list->last = NULL;
  199. }
  200. int LinkedList2_IsEmpty (LinkedList2 *list)
  201. {
  202. return (!list->first);
  203. }
  204. LinkedList2Node * LinkedList2_GetFirst (LinkedList2 *list)
  205. {
  206. return (list->first);
  207. }
  208. LinkedList2Node * LinkedList2_GetLast (LinkedList2 *list)
  209. {
  210. return (list->last);
  211. }
  212. void LinkedList2_Prepend (LinkedList2 *list, LinkedList2Node *node)
  213. {
  214. node->p = NULL;
  215. node->n = list->first;
  216. if (list->first) {
  217. list->first->p = node;
  218. } else {
  219. list->last = node;
  220. }
  221. list->first = node;
  222. node->it = NULL;
  223. }
  224. void LinkedList2_Append (LinkedList2 *list, LinkedList2Node *node)
  225. {
  226. node->p = list->last;
  227. node->n = NULL;
  228. if (list->last) {
  229. list->last->n = node;
  230. } else {
  231. list->first = node;
  232. }
  233. list->last = node;
  234. node->it = NULL;
  235. }
  236. void LinkedList2_InsertBefore (LinkedList2 *list, LinkedList2Node *node, LinkedList2Node *target)
  237. {
  238. node->p = target->p;
  239. node->n = target;
  240. if (target->p) {
  241. target->p->n = node;
  242. } else {
  243. list->first = node;
  244. }
  245. target->p = node;
  246. node->it = NULL;
  247. }
  248. void LinkedList2_InsertAfter (LinkedList2 *list, LinkedList2Node *node, LinkedList2Node *target)
  249. {
  250. node->p = target;
  251. node->n = target->n;
  252. if (target->n) {
  253. target->n->p = node;
  254. } else {
  255. list->last = node;
  256. }
  257. target->n = node;
  258. node->it = NULL;
  259. }
  260. void LinkedList2_Remove (LinkedList2 *list, LinkedList2Node *node)
  261. {
  262. // jump iterators
  263. while (node->it) {
  264. LinkedList2Iterator_Next(node->it);
  265. }
  266. // remove from list
  267. if (node->p) {
  268. node->p->n = node->n;
  269. } else {
  270. list->first = node->n;
  271. }
  272. if (node->n) {
  273. node->n->p = node->p;
  274. } else {
  275. list->last = node->p;
  276. }
  277. }
  278. LinkedList2Node * LinkedList2Node_Next (LinkedList2Node *node)
  279. {
  280. return node->n;
  281. }
  282. LinkedList2Node * LinkedList2Node_Prev (LinkedList2Node *node)
  283. {
  284. return node->p;
  285. }
  286. void LinkedList2Iterator_Init (LinkedList2Iterator *it, LinkedList2 *list, int dir, LinkedList2Node *node)
  287. {
  288. ASSERT(dir == 1 || dir == -1)
  289. it->list = list;
  290. it->dir = dir;
  291. it->e = node;
  292. if (it->e) {
  293. // link into node's iterator list
  294. it->pi = NULL;
  295. it->ni = it->e->it;
  296. if (it->e->it) {
  297. it->e->it->pi = it;
  298. }
  299. it->e->it = it;
  300. }
  301. }
  302. void LinkedList2Iterator_Free (LinkedList2Iterator *it)
  303. {
  304. if (it->e) {
  305. // remove from node's iterator list
  306. if (it->ni) {
  307. it->ni->pi = it->pi;
  308. }
  309. if (it->pi) {
  310. it->pi->ni = it->ni;
  311. } else {
  312. it->e->it = it->ni;
  313. }
  314. }
  315. }
  316. void LinkedList2Iterator_InitForward (LinkedList2Iterator *it, LinkedList2 *list)
  317. {
  318. LinkedList2Iterator_Init(it, list, 1, list->first);
  319. }
  320. void LinkedList2Iterator_InitBackward (LinkedList2Iterator *it, LinkedList2 *list)
  321. {
  322. LinkedList2Iterator_Init(it, list, -1, list->last);
  323. }
  324. LinkedList2Node * LinkedList2Iterator_Next (LinkedList2Iterator *it)
  325. {
  326. // remember original entry
  327. LinkedList2Node *orig = it->e;
  328. // jump to next entry
  329. if (it->e) {
  330. // get next entry
  331. LinkedList2Node *next;
  332. switch (it->dir) {
  333. case 1:
  334. next = it->e->n;
  335. break;
  336. case -1:
  337. next = it->e->p;
  338. break;
  339. default:
  340. ASSERT(0);
  341. }
  342. // destroy interator
  343. LinkedList2Iterator_Free(it);
  344. // re-initialize at next entry
  345. LinkedList2Iterator_Init(it, it->list, it->dir, next);
  346. }
  347. // return original entry
  348. return orig;
  349. }
  350. #endif