LinkedList3.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. typedef struct _LinkedList3Node {
  34. struct _LinkedList3Node *p;
  35. struct _LinkedList3Node *n;
  36. struct _LinkedList3Iterator *it;
  37. } LinkedList3Node;
  38. typedef struct _LinkedList3Iterator {
  39. int dir;
  40. struct _LinkedList3Node *e;
  41. struct _LinkedList3Iterator *pi;
  42. struct _LinkedList3Iterator *ni;
  43. } LinkedList3Iterator;
  44. static void LinkedList3Node_InitLonely (LinkedList3Node *node);
  45. static void LinkedList3Node_InitAfter (LinkedList3Node *node, LinkedList3Node *ref);
  46. static void LinkedList3Node_InitBefore (LinkedList3Node *node, LinkedList3Node *ref);
  47. static void LinkedList3Node_Free (LinkedList3Node *node);
  48. static int LinkedList3Node_IsLonely (LinkedList3Node *node);
  49. static LinkedList3Node * LinkedList3Node_PrevOrNext (LinkedList3Node *node);
  50. static LinkedList3Node * LinkedList3Node_NextOrPrev (LinkedList3Node *node);
  51. static LinkedList3Node * LinkedList3Node_Prev (LinkedList3Node *node);
  52. static LinkedList3Node * LinkedList3Node_Next (LinkedList3Node *node);
  53. static LinkedList3Node * LinkedList3Node_First (LinkedList3Node *node);
  54. static LinkedList3Node * LinkedList3Node_Last (LinkedList3Node *node);
  55. static void LinkedList3Iterator_Init (LinkedList3Iterator *it, LinkedList3Node *e, int dir);
  56. static void LinkedList3Iterator_Free (LinkedList3Iterator *it);
  57. static LinkedList3Node * LinkedList3Iterator_Next (LinkedList3Iterator *it);
  58. void LinkedList3Node_InitLonely (LinkedList3Node *node)
  59. {
  60. node->p = NULL;
  61. node->n = NULL;
  62. node->it = NULL;
  63. }
  64. void LinkedList3Node_InitAfter (LinkedList3Node *node, LinkedList3Node *ref)
  65. {
  66. ASSERT(ref)
  67. node->p = ref;
  68. node->n = ref->n;
  69. ref->n = node;
  70. if (node->n) {
  71. node->n->p = node;
  72. }
  73. node->it = NULL;
  74. }
  75. void LinkedList3Node_InitBefore (LinkedList3Node *node, LinkedList3Node *ref)
  76. {
  77. ASSERT(ref)
  78. node->n = ref;
  79. node->p = ref->p;
  80. ref->p = node;
  81. if (node->p) {
  82. node->p->n = node;
  83. }
  84. node->it = NULL;
  85. }
  86. void LinkedList3Node_Free (LinkedList3Node *node)
  87. {
  88. // jump iterators
  89. while (node->it) {
  90. LinkedList3Iterator_Next(node->it);
  91. }
  92. if (node->p) {
  93. node->p->n = node->n;
  94. }
  95. if (node->n) {
  96. node->n->p = node->p;
  97. }
  98. }
  99. int LinkedList3Node_IsLonely (LinkedList3Node *node)
  100. {
  101. return (!node->p && !node->n);
  102. }
  103. LinkedList3Node * LinkedList3Node_PrevOrNext (LinkedList3Node *node)
  104. {
  105. if (node->p) {
  106. return node->p;
  107. }
  108. if (node->n) {
  109. return node->n;
  110. }
  111. return NULL;
  112. }
  113. LinkedList3Node * LinkedList3Node_NextOrPrev (LinkedList3Node *node)
  114. {
  115. if (node->n) {
  116. return node->n;
  117. }
  118. if (node->p) {
  119. return node->p;
  120. }
  121. return NULL;
  122. }
  123. LinkedList3Node * LinkedList3Node_Prev (LinkedList3Node *node)
  124. {
  125. return node->p;
  126. }
  127. LinkedList3Node * LinkedList3Node_Next (LinkedList3Node *node)
  128. {
  129. return node->n;
  130. }
  131. LinkedList3Node * LinkedList3Node_First (LinkedList3Node *node)
  132. {
  133. while (node->p) {
  134. node = node->p;
  135. }
  136. return node;
  137. }
  138. LinkedList3Node * LinkedList3Node_Last (LinkedList3Node *node)
  139. {
  140. while (node->n) {
  141. node = node->n;
  142. }
  143. return node;
  144. }
  145. void LinkedList3Iterator_Init (LinkedList3Iterator *it, LinkedList3Node *e, int dir)
  146. {
  147. ASSERT(dir == -1 || dir == 1)
  148. it->dir = dir;
  149. it->e = e;
  150. if (e) {
  151. // link into node's iterator list
  152. it->pi = NULL;
  153. it->ni = e->it;
  154. if (e->it) {
  155. e->it->pi = it;
  156. }
  157. e->it = it;
  158. }
  159. }
  160. void LinkedList3Iterator_Free (LinkedList3Iterator *it)
  161. {
  162. if (it->e) {
  163. // remove from node's iterator list
  164. if (it->ni) {
  165. it->ni->pi = it->pi;
  166. }
  167. if (it->pi) {
  168. it->pi->ni = it->ni;
  169. } else {
  170. it->e->it = it->ni;
  171. }
  172. }
  173. }
  174. LinkedList3Node * LinkedList3Iterator_Next (LinkedList3Iterator *it)
  175. {
  176. // remember original entry
  177. LinkedList3Node *orig = it->e;
  178. // jump to next entry
  179. if (it->e) {
  180. // get next entry
  181. LinkedList3Node *next;
  182. switch (it->dir) {
  183. case 1:
  184. next = it->e->n;
  185. break;
  186. case -1:
  187. next = it->e->p;
  188. break;
  189. default:
  190. ASSERT(0);
  191. }
  192. // destroy interator
  193. LinkedList3Iterator_Free(it);
  194. // re-initialize at next entry
  195. LinkedList3Iterator_Init(it, next, it->dir);
  196. }
  197. // return original entry
  198. return orig;
  199. }
  200. #endif