list.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #ifndef OSSL_INTERNAL_LIST_H
  10. # define OSSL_INTERNAL_LIST_H
  11. # pragma once
  12. # include <string.h>
  13. # include <assert.h>
  14. # ifdef NDEBUG
  15. # define OSSL_LIST_DBG(x)
  16. # else
  17. # define OSSL_LIST_DBG(x) x;
  18. # endif
  19. /* Define a list structure */
  20. # define OSSL_LIST(name) OSSL_LIST_ ## name
  21. /* Define fields to include an element of a list */
  22. # define OSSL_LIST_MEMBER(name, type) \
  23. struct { \
  24. type *next, *prev; \
  25. OSSL_LIST_DBG(struct ossl_list_st_ ## name *list) \
  26. } ossl_list_ ## name
  27. # define DEFINE_LIST_OF(name, type) \
  28. typedef struct ossl_list_st_ ## name OSSL_LIST(name); \
  29. struct ossl_list_st_ ## name { \
  30. type *alpha, *omega; \
  31. size_t num_elems; \
  32. }; \
  33. static ossl_unused ossl_inline void \
  34. ossl_list_##name##_init(OSSL_LIST(name) *list) \
  35. { \
  36. memset(list, 0, sizeof(*list)); \
  37. } \
  38. static ossl_unused ossl_inline void \
  39. ossl_list_##name##_init_elem(type *elem) \
  40. { \
  41. memset(&elem->ossl_list_ ## name, 0, \
  42. sizeof(elem->ossl_list_ ## name)); \
  43. } \
  44. static ossl_unused ossl_inline int \
  45. ossl_list_##name##_is_empty(const OSSL_LIST(name) *list) \
  46. { \
  47. return list->num_elems == 0; \
  48. } \
  49. static ossl_unused ossl_inline size_t \
  50. ossl_list_##name##_num(const OSSL_LIST(name) *list) \
  51. { \
  52. return list->num_elems; \
  53. } \
  54. static ossl_unused ossl_inline type * \
  55. ossl_list_##name##_head(const OSSL_LIST(name) *list) \
  56. { \
  57. assert(list->alpha == NULL \
  58. || list->alpha->ossl_list_ ## name.list == list); \
  59. return list->alpha; \
  60. } \
  61. static ossl_unused ossl_inline type * \
  62. ossl_list_##name##_tail(const OSSL_LIST(name) *list) \
  63. { \
  64. assert(list->omega == NULL \
  65. || list->omega->ossl_list_ ## name.list == list); \
  66. return list->omega; \
  67. } \
  68. static ossl_unused ossl_inline type * \
  69. ossl_list_##name##_next(const type *elem) \
  70. { \
  71. assert(elem->ossl_list_ ## name.next == NULL \
  72. || elem->ossl_list_ ## name.next \
  73. ->ossl_list_ ## name.prev == elem); \
  74. return elem->ossl_list_ ## name.next; \
  75. } \
  76. static ossl_unused ossl_inline type * \
  77. ossl_list_##name##_prev(const type *elem) \
  78. { \
  79. assert(elem->ossl_list_ ## name.prev == NULL \
  80. || elem->ossl_list_ ## name.prev \
  81. ->ossl_list_ ## name.next == elem); \
  82. return elem->ossl_list_ ## name.prev; \
  83. } \
  84. static ossl_unused ossl_inline void \
  85. ossl_list_##name##_remove(OSSL_LIST(name) *list, type *elem) \
  86. { \
  87. assert(elem->ossl_list_ ## name.list == list); \
  88. OSSL_LIST_DBG(elem->ossl_list_ ## name.list = NULL) \
  89. if (list->alpha == elem) \
  90. list->alpha = elem->ossl_list_ ## name.next; \
  91. if (list->omega == elem) \
  92. list->omega = elem->ossl_list_ ## name.prev; \
  93. if (elem->ossl_list_ ## name.prev != NULL) \
  94. elem->ossl_list_ ## name.prev->ossl_list_ ## name.next = \
  95. elem->ossl_list_ ## name.next; \
  96. if (elem->ossl_list_ ## name.next != NULL) \
  97. elem->ossl_list_ ## name.next->ossl_list_ ## name.prev = \
  98. elem->ossl_list_ ## name.prev; \
  99. list->num_elems--; \
  100. memset(&elem->ossl_list_ ## name, 0, \
  101. sizeof(elem->ossl_list_ ## name)); \
  102. } \
  103. static ossl_unused ossl_inline void \
  104. ossl_list_##name##_insert_head(OSSL_LIST(name) *list, type *elem) \
  105. { \
  106. assert(elem->ossl_list_ ## name.list == NULL); \
  107. OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
  108. if (list->alpha != NULL) \
  109. list->alpha->ossl_list_ ## name.prev = elem; \
  110. elem->ossl_list_ ## name.next = list->alpha; \
  111. elem->ossl_list_ ## name.prev = NULL; \
  112. list->alpha = elem; \
  113. if (list->omega == NULL) \
  114. list->omega = elem; \
  115. list->num_elems++; \
  116. } \
  117. static ossl_unused ossl_inline void \
  118. ossl_list_##name##_insert_tail(OSSL_LIST(name) *list, type *elem) \
  119. { \
  120. assert(elem->ossl_list_ ## name.list == NULL); \
  121. OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
  122. if (list->omega != NULL) \
  123. list->omega->ossl_list_ ## name.next = elem; \
  124. elem->ossl_list_ ## name.prev = list->omega; \
  125. elem->ossl_list_ ## name.next = NULL; \
  126. list->omega = elem; \
  127. if (list->alpha == NULL) \
  128. list->alpha = elem; \
  129. list->num_elems++; \
  130. } \
  131. static ossl_unused ossl_inline void \
  132. ossl_list_##name##_insert_before(OSSL_LIST(name) *list, type *e, \
  133. type *elem) \
  134. { \
  135. assert(elem->ossl_list_ ## name.list == NULL); \
  136. OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
  137. elem->ossl_list_ ## name.next = e; \
  138. elem->ossl_list_ ## name.prev = e->ossl_list_ ## name.prev; \
  139. if (e->ossl_list_ ## name.prev != NULL) \
  140. e->ossl_list_ ## name.prev->ossl_list_ ## name.next = elem; \
  141. e->ossl_list_ ## name.prev = elem; \
  142. if (list->alpha == e) \
  143. list->alpha = elem; \
  144. list->num_elems++; \
  145. } \
  146. static ossl_unused ossl_inline void \
  147. ossl_list_##name##_insert_after(OSSL_LIST(name) *list, type *e, \
  148. type *elem) \
  149. { \
  150. assert(elem->ossl_list_ ## name.list == NULL); \
  151. OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
  152. elem->ossl_list_ ## name.prev = e; \
  153. elem->ossl_list_ ## name.next = e->ossl_list_ ## name.next; \
  154. if (e->ossl_list_ ## name.next != NULL) \
  155. e->ossl_list_ ## name.next->ossl_list_ ## name.prev = elem; \
  156. e->ossl_list_ ## name.next = elem; \
  157. if (list->omega == e) \
  158. list->omega = elem; \
  159. list->num_elems++; \
  160. } \
  161. struct ossl_list_st_ ## name
  162. #endif