LinkedList3.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /**
  2. * @file LinkedList3.h
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * @section DESCRIPTION
  30. *
  31. * Doubly linked list that support multiple iterations and removing
  32. * aritrary elements during iteration, without a central object to
  33. * represent the list.
  34. */
  35. #ifndef BADVPN_STRUCTURE_LINKEDLIST3_H
  36. #define BADVPN_STRUCTURE_LINKEDLIST3_H
  37. #include <stddef.h>
  38. #include <stdint.h>
  39. #include <misc/debug.h>
  40. struct _LinkedList3Iterator;
  41. /**
  42. * Linked list node.
  43. */
  44. typedef struct _LinkedList3Node {
  45. struct _LinkedList3Node *p;
  46. struct _LinkedList3Node *n;
  47. struct _LinkedList3Iterator *it;
  48. } LinkedList3Node;
  49. /**
  50. * Linked list iterator.
  51. */
  52. typedef struct _LinkedList3Iterator {
  53. int8_t dir;
  54. struct _LinkedList3Node *e;
  55. struct _LinkedList3Iterator *pi;
  56. struct _LinkedList3Iterator *ni;
  57. } LinkedList3Iterator;
  58. /**
  59. * Initializes a list node to form a new list consisting of a
  60. * single 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. */
  66. static void LinkedList3Node_InitLonely (LinkedList3Node *node);
  67. /**
  68. * Initializes a list node to go after an existing node.
  69. *
  70. * @param node list node structure to initialize. The node must remain
  71. * available until it is freed with {@link LinkedList3Node_Free},
  72. * or the list is no longer required.
  73. * @param ref existing list node
  74. */
  75. static void LinkedList3Node_InitAfter (LinkedList3Node *node, LinkedList3Node *ref);
  76. /**
  77. * Initializes a list node to go before an existing node.
  78. *
  79. * @param node list node structure to initialize. The node must remain
  80. * available until it is freed with {@link LinkedList3Node_Free},
  81. * or the list is no longer required.
  82. * @param ref existing list node
  83. */
  84. static void LinkedList3Node_InitBefore (LinkedList3Node *node, LinkedList3Node *ref);
  85. /**
  86. * Frees a list node, removing it a list (if there were other nodes
  87. * in the list).
  88. *
  89. * @param node list node to free
  90. */
  91. static void LinkedList3Node_Free (LinkedList3Node *node);
  92. /**
  93. * Determines if a list node is a single node in a list.
  94. *
  95. * @param node list node
  96. * @return 1 if the node ia a single node, 0 if not
  97. */
  98. static int LinkedList3Node_IsLonely (LinkedList3Node *node);
  99. /**
  100. * Returnes the node preceding this node (if there is one),
  101. * the node following this node (if there is one), or NULL,
  102. * respectively.
  103. *
  104. * @param node list node
  105. * @return neighbour node or NULL if none
  106. */
  107. static LinkedList3Node * LinkedList3Node_PrevOrNext (LinkedList3Node *node);
  108. /**
  109. * Returnes the node following this node (if there is one),
  110. * the node preceding this node (if there is one), or NULL,
  111. * respectively.
  112. *
  113. * @param node list node
  114. * @return neighbour node or NULL if none
  115. */
  116. static LinkedList3Node * LinkedList3Node_NextOrPrev (LinkedList3Node *node);
  117. /**
  118. * Returns the node preceding this node, or NULL if there is none.
  119. *
  120. * @param node list node
  121. * @return left neighbour, or NULL if none
  122. */
  123. static LinkedList3Node * LinkedList3Node_Prev (LinkedList3Node *node);
  124. /**
  125. * Returns the node following this node, or NULL if there is none.
  126. *
  127. * @param node list node
  128. * @return right neighbour, or NULL if none
  129. */
  130. static LinkedList3Node * LinkedList3Node_Next (LinkedList3Node *node);
  131. /**
  132. * Returns the first node in the list which this node is part of.
  133. * It is found by iterating the list from this node to the beginning.
  134. *
  135. * @param node list node
  136. * @return first node in the list
  137. */
  138. static LinkedList3Node * LinkedList3Node_First (LinkedList3Node *node);
  139. /**
  140. * Returns the last node in the list which this node is part of.
  141. * It is found by iterating the list from this node to the end.
  142. *
  143. * @param node list node
  144. * @return last node in the list
  145. */
  146. static LinkedList3Node * LinkedList3Node_Last (LinkedList3Node *node);
  147. /**
  148. * Initializes a linked list iterator.
  149. * The iterator structure must remain available until either of these occurs:
  150. * - the list is no longer needed, or
  151. * - the iterator is freed with {@link LinkedList3Iterator_Free}, or
  152. * - the iterator reaches the end of iteration.
  153. *
  154. * @param it uninitialized iterator to initialize
  155. * @param e initial position of the iterator. NULL for end of iteration.
  156. * @param dir direction of iteration. Must be 1 (forward) or -1 (backward).
  157. */
  158. static void LinkedList3Iterator_Init (LinkedList3Iterator *it, LinkedList3Node *e, int dir);
  159. /**
  160. * Frees a linked list iterator.
  161. *
  162. * @param it iterator to free
  163. */
  164. static void LinkedList3Iterator_Free (LinkedList3Iterator *it);
  165. /**
  166. * Moves the iterator one node forward or backward (depending on its direction), or,
  167. * if it's at the last or first node (depending on the direction), it reaches
  168. * the end of iteration, or, if it's at the end of iteration, it remains there.
  169. * Returns the the previous position.
  170. *
  171. * @param it the iterator
  172. * @return node on the position of iterator before it was (possibly) moved, or NULL
  173. * if it was at the end of iteration
  174. */
  175. static LinkedList3Node * LinkedList3Iterator_Next (LinkedList3Iterator *it);
  176. void LinkedList3Node_InitLonely (LinkedList3Node *node)
  177. {
  178. node->p = NULL;
  179. node->n = NULL;
  180. node->it = NULL;
  181. }
  182. void LinkedList3Node_InitAfter (LinkedList3Node *node, LinkedList3Node *ref)
  183. {
  184. ASSERT(ref)
  185. node->p = ref;
  186. node->n = ref->n;
  187. ref->n = node;
  188. if (node->n) {
  189. node->n->p = node;
  190. }
  191. node->it = NULL;
  192. }
  193. void LinkedList3Node_InitBefore (LinkedList3Node *node, LinkedList3Node *ref)
  194. {
  195. ASSERT(ref)
  196. node->n = ref;
  197. node->p = ref->p;
  198. ref->p = node;
  199. if (node->p) {
  200. node->p->n = node;
  201. }
  202. node->it = NULL;
  203. }
  204. void LinkedList3Node_Free (LinkedList3Node *node)
  205. {
  206. // jump iterators
  207. while (node->it) {
  208. LinkedList3Iterator_Next(node->it);
  209. }
  210. if (node->p) {
  211. node->p->n = node->n;
  212. }
  213. if (node->n) {
  214. node->n->p = node->p;
  215. }
  216. }
  217. int LinkedList3Node_IsLonely (LinkedList3Node *node)
  218. {
  219. return (!node->p && !node->n);
  220. }
  221. LinkedList3Node * LinkedList3Node_PrevOrNext (LinkedList3Node *node)
  222. {
  223. if (node->p) {
  224. return node->p;
  225. }
  226. if (node->n) {
  227. return node->n;
  228. }
  229. return NULL;
  230. }
  231. LinkedList3Node * LinkedList3Node_NextOrPrev (LinkedList3Node *node)
  232. {
  233. if (node->n) {
  234. return node->n;
  235. }
  236. if (node->p) {
  237. return node->p;
  238. }
  239. return NULL;
  240. }
  241. LinkedList3Node * LinkedList3Node_Prev (LinkedList3Node *node)
  242. {
  243. return node->p;
  244. }
  245. LinkedList3Node * LinkedList3Node_Next (LinkedList3Node *node)
  246. {
  247. return node->n;
  248. }
  249. LinkedList3Node * LinkedList3Node_First (LinkedList3Node *node)
  250. {
  251. while (node->p) {
  252. node = node->p;
  253. }
  254. return node;
  255. }
  256. LinkedList3Node * LinkedList3Node_Last (LinkedList3Node *node)
  257. {
  258. while (node->n) {
  259. node = node->n;
  260. }
  261. return node;
  262. }
  263. void LinkedList3Iterator_Init (LinkedList3Iterator *it, LinkedList3Node *e, int dir)
  264. {
  265. ASSERT(dir == -1 || dir == 1)
  266. it->dir = dir;
  267. it->e = e;
  268. if (e) {
  269. // link into node's iterator list
  270. it->pi = NULL;
  271. it->ni = e->it;
  272. if (e->it) {
  273. e->it->pi = it;
  274. }
  275. e->it = it;
  276. }
  277. }
  278. void LinkedList3Iterator_Free (LinkedList3Iterator *it)
  279. {
  280. if (it->e) {
  281. // remove from node's iterator list
  282. if (it->ni) {
  283. it->ni->pi = it->pi;
  284. }
  285. if (it->pi) {
  286. it->pi->ni = it->ni;
  287. } else {
  288. it->e->it = it->ni;
  289. }
  290. }
  291. }
  292. LinkedList3Node * LinkedList3Iterator_Next (LinkedList3Iterator *it)
  293. {
  294. // remember original entry
  295. LinkedList3Node *orig = it->e;
  296. // jump to next entry
  297. if (it->e) {
  298. // get next entry
  299. LinkedList3Node *next;
  300. switch (it->dir) {
  301. case 1:
  302. next = it->e->n;
  303. break;
  304. case -1:
  305. next = it->e->p;
  306. break;
  307. default:
  308. ASSERT(0);
  309. }
  310. // destroy interator
  311. LinkedList3Iterator_Free(it);
  312. // re-initialize at next entry
  313. LinkedList3Iterator_Init(it, next, it->dir);
  314. }
  315. // return original entry
  316. return orig;
  317. }
  318. #endif