LinkedList3.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /**
  2. * @file LinkedList3.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, without a central object to
  26. * represent the list.
  27. */
  28. #ifndef BADVPN_STRUCTURE_LINKEDLIST3_H
  29. #define BADVPN_STRUCTURE_LINKEDLIST3_H
  30. #include <stddef.h>
  31. #include <misc/debug.h>
  32. struct _LinkedList3Iterator;
  33. /**
  34. * Linked list node.
  35. */
  36. typedef struct _LinkedList3Node {
  37. struct _LinkedList3Node *p;
  38. struct _LinkedList3Node *n;
  39. struct _LinkedList3Iterator *it;
  40. } LinkedList3Node;
  41. /**
  42. * Linked list iterator.
  43. */
  44. typedef struct _LinkedList3Iterator {
  45. int dir;
  46. struct _LinkedList3Node *e;
  47. struct _LinkedList3Iterator *pi;
  48. struct _LinkedList3Iterator *ni;
  49. } LinkedList3Iterator;
  50. /**
  51. * Initializes a list node to form a new list consisting of a
  52. * single node.
  53. *
  54. * @param node list node structure to initialize. The node must remain
  55. * available until it is freed with {@link LinkedList3Node_Free},
  56. * or the list is no longer required.
  57. */
  58. static void LinkedList3Node_InitLonely (LinkedList3Node *node);
  59. /**
  60. * Initializes a list node to go after an existing node.
  61. *
  62. * @param node list node structure to initialize. The node must remain
  63. * available until it is freed with {@link LinkedList3Node_Free},
  64. * or the list is no longer required.
  65. * @param ref existing list node
  66. */
  67. static void LinkedList3Node_InitAfter (LinkedList3Node *node, LinkedList3Node *ref);
  68. /**
  69. * Initializes a list node to go before an existing node.
  70. *
  71. * @param node list node structure to initialize. The node must remain
  72. * available until it is freed with {@link LinkedList3Node_Free},
  73. * or the list is no longer required.
  74. * @param ref existing list node
  75. */
  76. static void LinkedList3Node_InitBefore (LinkedList3Node *node, LinkedList3Node *ref);
  77. /**
  78. * Frees a list node, removing it a list (if there were other nodes
  79. * in the list).
  80. *
  81. * @param node list node to free
  82. */
  83. static void LinkedList3Node_Free (LinkedList3Node *node);
  84. /**
  85. * Determines if a list node is a single node in a list.
  86. *
  87. * @param node list node
  88. * @return 1 if the node ia a single node, 0 if not
  89. */
  90. static int LinkedList3Node_IsLonely (LinkedList3Node *node);
  91. /**
  92. * Returnes the node preceding this node (if there is one),
  93. * the node following this node (if there is one), or NULL,
  94. * respectively.
  95. *
  96. * @param node list node
  97. * @return neighbour node or NULL if none
  98. */
  99. static LinkedList3Node * LinkedList3Node_PrevOrNext (LinkedList3Node *node);
  100. /**
  101. * Returnes the node following this node (if there is one),
  102. * the node preceding this node (if there is one), or NULL,
  103. * respectively.
  104. *
  105. * @param node list node
  106. * @return neighbour node or NULL if none
  107. */
  108. static LinkedList3Node * LinkedList3Node_NextOrPrev (LinkedList3Node *node);
  109. /**
  110. * Returns the node preceding this node, or NULL if there is none.
  111. *
  112. * @param node list node
  113. * @return left neighbour, or NULL if none
  114. */
  115. static LinkedList3Node * LinkedList3Node_Prev (LinkedList3Node *node);
  116. /**
  117. * Returns the node following this node, or NULL if there is none.
  118. *
  119. * @param node list node
  120. * @return right neighbour, or NULL if none
  121. */
  122. static LinkedList3Node * LinkedList3Node_Next (LinkedList3Node *node);
  123. /**
  124. * Returns the first node in the list which this node is part of.
  125. * It is found by iterating the list from this node to the beginning.
  126. *
  127. * @param node list node
  128. * @return first node in the list
  129. */
  130. static LinkedList3Node * LinkedList3Node_First (LinkedList3Node *node);
  131. /**
  132. * Returns the last node in the list which this node is part of.
  133. * It is found by iterating the list from this node to the end.
  134. *
  135. * @param node list node
  136. * @return last node in the list
  137. */
  138. static LinkedList3Node * LinkedList3Node_Last (LinkedList3Node *node);
  139. /**
  140. * Initializes a linked list iterator.
  141. * The iterator structure must remain available until either of these occurs:
  142. * - the list is no longer needed, or
  143. * - the iterator is freed with {@link LinkedList3Iterator_Free}, or
  144. * - the iterator reaches the end of iteration.
  145. *
  146. * @param it uninitialized iterator to initialize
  147. * @param e initial position of the iterator. NULL for end of iteration.
  148. * @param dir direction of iteration. Must be 1 (forward) or -1 (backward).
  149. */
  150. static void LinkedList3Iterator_Init (LinkedList3Iterator *it, LinkedList3Node *e, int dir);
  151. /**
  152. * Frees a linked list iterator.
  153. *
  154. * @param it iterator to free
  155. */
  156. static void LinkedList3Iterator_Free (LinkedList3Iterator *it);
  157. /**
  158. * Moves the iterator one node forward or backward (depending on its direction), or,
  159. * if it's at the last or first node (depending on the direction), it reaches
  160. * the end of iteration, or, if it's at the end of iteration, it remains there.
  161. * Returns the the previous position.
  162. *
  163. * @param it the iterator
  164. * @return node on the position of iterator before it was (possibly) moved, or NULL
  165. * if it was at the end of iteration
  166. */
  167. static LinkedList3Node * LinkedList3Iterator_Next (LinkedList3Iterator *it);
  168. void LinkedList3Node_InitLonely (LinkedList3Node *node)
  169. {
  170. node->p = NULL;
  171. node->n = NULL;
  172. node->it = NULL;
  173. }
  174. void LinkedList3Node_InitAfter (LinkedList3Node *node, LinkedList3Node *ref)
  175. {
  176. ASSERT(ref)
  177. node->p = ref;
  178. node->n = ref->n;
  179. ref->n = node;
  180. if (node->n) {
  181. node->n->p = node;
  182. }
  183. node->it = NULL;
  184. }
  185. void LinkedList3Node_InitBefore (LinkedList3Node *node, LinkedList3Node *ref)
  186. {
  187. ASSERT(ref)
  188. node->n = ref;
  189. node->p = ref->p;
  190. ref->p = node;
  191. if (node->p) {
  192. node->p->n = node;
  193. }
  194. node->it = NULL;
  195. }
  196. void LinkedList3Node_Free (LinkedList3Node *node)
  197. {
  198. // jump iterators
  199. while (node->it) {
  200. LinkedList3Iterator_Next(node->it);
  201. }
  202. if (node->p) {
  203. node->p->n = node->n;
  204. }
  205. if (node->n) {
  206. node->n->p = node->p;
  207. }
  208. }
  209. int LinkedList3Node_IsLonely (LinkedList3Node *node)
  210. {
  211. return (!node->p && !node->n);
  212. }
  213. LinkedList3Node * LinkedList3Node_PrevOrNext (LinkedList3Node *node)
  214. {
  215. if (node->p) {
  216. return node->p;
  217. }
  218. if (node->n) {
  219. return node->n;
  220. }
  221. return NULL;
  222. }
  223. LinkedList3Node * LinkedList3Node_NextOrPrev (LinkedList3Node *node)
  224. {
  225. if (node->n) {
  226. return node->n;
  227. }
  228. if (node->p) {
  229. return node->p;
  230. }
  231. return NULL;
  232. }
  233. LinkedList3Node * LinkedList3Node_Prev (LinkedList3Node *node)
  234. {
  235. return node->p;
  236. }
  237. LinkedList3Node * LinkedList3Node_Next (LinkedList3Node *node)
  238. {
  239. return node->n;
  240. }
  241. LinkedList3Node * LinkedList3Node_First (LinkedList3Node *node)
  242. {
  243. while (node->p) {
  244. node = node->p;
  245. }
  246. return node;
  247. }
  248. LinkedList3Node * LinkedList3Node_Last (LinkedList3Node *node)
  249. {
  250. while (node->n) {
  251. node = node->n;
  252. }
  253. return node;
  254. }
  255. void LinkedList3Iterator_Init (LinkedList3Iterator *it, LinkedList3Node *e, int dir)
  256. {
  257. ASSERT(dir == -1 || dir == 1)
  258. it->dir = dir;
  259. it->e = e;
  260. if (e) {
  261. // link into node's iterator list
  262. it->pi = NULL;
  263. it->ni = e->it;
  264. if (e->it) {
  265. e->it->pi = it;
  266. }
  267. e->it = it;
  268. }
  269. }
  270. void LinkedList3Iterator_Free (LinkedList3Iterator *it)
  271. {
  272. if (it->e) {
  273. // remove from node's iterator list
  274. if (it->ni) {
  275. it->ni->pi = it->pi;
  276. }
  277. if (it->pi) {
  278. it->pi->ni = it->ni;
  279. } else {
  280. it->e->it = it->ni;
  281. }
  282. }
  283. }
  284. LinkedList3Node * LinkedList3Iterator_Next (LinkedList3Iterator *it)
  285. {
  286. // remember original entry
  287. LinkedList3Node *orig = it->e;
  288. // jump to next entry
  289. if (it->e) {
  290. // get next entry
  291. LinkedList3Node *next;
  292. switch (it->dir) {
  293. case 1:
  294. next = it->e->n;
  295. break;
  296. case -1:
  297. next = it->e->p;
  298. break;
  299. default:
  300. ASSERT(0);
  301. }
  302. // destroy interator
  303. LinkedList3Iterator_Free(it);
  304. // re-initialize at next entry
  305. LinkedList3Iterator_Init(it, next, it->dir);
  306. }
  307. // return original entry
  308. return orig;
  309. }
  310. #endif