linklist.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #ifndef LINKLIST_H_INCLUDED
  2. #define LINKLIST_H_INCLUDED
  3. #include "inline.h"
  4. struct list_head {
  5. /*----------------------------------------------------------------------------
  6. This is a header for an element of a doubly linked list, or an anchor
  7. for such a list.
  8. itemP == NULL means it's an anchor; otherwise it's a header.
  9. Initialize a list header with list_init_header(). You don't have to
  10. do anything to terminate a list header.
  11. Initialize an anchor with list_make_emtpy(). You don't have to do anything
  12. to terminate a list header.
  13. -----------------------------------------------------------------------------*/
  14. struct list_head * nextP;
  15. /* For a header, this is the address of the list header for
  16. the next element in the list. If there is no next element,
  17. it points to the anchor. If the header is not in a list at
  18. all, it is NULL.
  19. For an anchor, it is the address of the list header of the
  20. first element. If the list is empty, it points to the
  21. anchor itself.
  22. */
  23. struct list_head * prevP;
  24. /* For a header, this is the address of the list header for
  25. the previous element in the list. If there is no previous element,
  26. it points to the anchor. If the header is not in a list at
  27. all, it is NULL.
  28. For an anchor, it is the address of the list header of the
  29. last element. If the list is empty, it points to the
  30. anchor itself.
  31. */
  32. void * itemP;
  33. /* For a header, this is the address of the list element to which it
  34. belongs. For an anchor, this is NULL.
  35. */
  36. };
  37. static __inline__ void
  38. list_init_header(struct list_head * const headerP,
  39. void * const itemP) {
  40. headerP->prevP = NULL;
  41. headerP->nextP = NULL;
  42. headerP->itemP = itemP;
  43. }
  44. static __inline__ int
  45. list_is_linked(struct list_head * headerP) {
  46. return headerP->prevP != NULL;
  47. }
  48. static __inline__ int
  49. list_is_empty(struct list_head * const anchorP) {
  50. return anchorP->nextP == anchorP;
  51. }
  52. static __inline__ unsigned int
  53. list_count(struct list_head * const anchorP) {
  54. unsigned int count;
  55. struct list_head * p;
  56. for (p = anchorP->nextP, count = 0;
  57. p != anchorP;
  58. p = p->nextP, ++count);
  59. return count;
  60. }
  61. static __inline__ void
  62. list_make_empty(struct list_head * const anchorP) {
  63. anchorP->prevP = anchorP;
  64. anchorP->nextP = anchorP;
  65. anchorP->itemP = NULL;
  66. }
  67. static __inline__ void
  68. list_insert_after(struct list_head * const beforeHeaderP,
  69. struct list_head * const newHeaderP) {
  70. newHeaderP->prevP = beforeHeaderP;
  71. newHeaderP->nextP = beforeHeaderP->nextP;
  72. beforeHeaderP->nextP = newHeaderP;
  73. newHeaderP->nextP->prevP = newHeaderP;
  74. }
  75. static __inline__ void
  76. list_add_tail(struct list_head * const anchorP,
  77. struct list_head * const headerP) {
  78. list_insert_after(anchorP->prevP, headerP);
  79. }
  80. static __inline__ void
  81. list_add_head(struct list_head * const anchorP,
  82. struct list_head * const headerP) {
  83. list_insert_after(anchorP, headerP);
  84. }
  85. static __inline__ void
  86. list_remove(struct list_head * const headerP) {
  87. headerP->prevP->nextP = headerP->nextP;
  88. headerP->nextP->prevP = headerP->prevP;
  89. headerP->prevP = NULL;
  90. headerP->nextP = NULL;
  91. }
  92. static __inline__ struct list_head *
  93. list_remove_head(struct list_head * const anchorP) {
  94. struct list_head * retval;
  95. if (list_is_empty(anchorP))
  96. retval = NULL;
  97. else {
  98. retval = anchorP->nextP;
  99. list_remove(retval);
  100. }
  101. return retval;
  102. }
  103. static __inline__ struct list_head *
  104. list_remove_tail(struct list_head * const anchorP) {
  105. struct list_head * retval;
  106. if (list_is_empty(anchorP))
  107. retval = NULL;
  108. else {
  109. retval = anchorP->prevP;
  110. list_remove(retval);
  111. }
  112. return retval;
  113. }
  114. static __inline__ void *
  115. list_foreach(struct list_head * const anchorP,
  116. void * functionP(struct list_head *, void *),
  117. void * const context) {
  118. struct list_head * p;
  119. struct list_head * nextP;
  120. void * result;
  121. for (p = anchorP->nextP, nextP = p->nextP, result=NULL;
  122. p != anchorP && result == NULL;
  123. p = nextP, nextP = p->nextP)
  124. result = (*functionP)(p, context);
  125. return result;
  126. }
  127. static __inline__ void
  128. list_append(struct list_head * const newAnchorP,
  129. struct list_head * const baseAnchorP) {
  130. if (!list_is_empty(newAnchorP)) {
  131. baseAnchorP->prevP->nextP = newAnchorP->nextP;
  132. newAnchorP->nextP->prevP = baseAnchorP->prevP;
  133. newAnchorP->prevP->nextP = baseAnchorP;
  134. baseAnchorP->prevP = newAnchorP->prevP;
  135. }
  136. }
  137. #endif