list.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #include "bt_common.h"
  2. #include "osi/allocator.h"
  3. #include "osi/list.h"
  4. #include "osi/osi.h"
  5. struct list_node_t {
  6. struct list_node_t *next;
  7. void *data;
  8. };
  9. typedef struct list_t {
  10. list_node_t *head;
  11. list_node_t *tail;
  12. size_t length;
  13. list_free_cb free_cb;
  14. } list_t;
  15. //static list_node_t *list_free_node_(list_t *list, list_node_t *node);
  16. // Hidden constructor, only to be used by the hash map for the allocation tracker.
  17. // Behaves the same as |list_new|, except you get to specify the allocator.
  18. list_t *list_new_internal(list_free_cb callback)
  19. {
  20. list_t *list = (list_t *) osi_calloc(sizeof(list_t));
  21. if (!list) {
  22. return NULL;
  23. }
  24. list->head = list->tail = NULL;
  25. list->length = 0;
  26. list->free_cb = callback;
  27. return list;
  28. }
  29. list_t *list_new(list_free_cb callback)
  30. {
  31. return list_new_internal(callback);
  32. }
  33. void list_free(list_t *list)
  34. {
  35. if (!list) {
  36. return;
  37. }
  38. list_clear(list);
  39. osi_free(list);
  40. }
  41. bool list_is_empty(const list_t *list)
  42. {
  43. assert(list != NULL);
  44. return (list->length == 0);
  45. }
  46. bool list_contains(const list_t *list, const void *data)
  47. {
  48. assert(list != NULL);
  49. assert(data != NULL);
  50. for (const list_node_t *node = list_begin(list); node != list_end(list); node = list_next(node)) {
  51. if (list_node(node) == data) {
  52. return true;
  53. }
  54. }
  55. return false;
  56. }
  57. size_t list_length(const list_t *list)
  58. {
  59. assert(list != NULL);
  60. return list->length;
  61. }
  62. void *list_front(const list_t *list)
  63. {
  64. assert(list != NULL);
  65. assert(!list_is_empty(list));
  66. return list->head->data;
  67. }
  68. void *list_back(const list_t *list) {
  69. assert(list != NULL);
  70. assert(!list_is_empty(list));
  71. return list->tail->data;
  72. }
  73. list_node_t *list_back_node(const list_t *list) {
  74. assert(list != NULL);
  75. assert(!list_is_empty(list));
  76. return list->tail;
  77. }
  78. bool list_insert_after(list_t *list, list_node_t *prev_node, void *data) {
  79. assert(list != NULL);
  80. assert(prev_node != NULL);
  81. assert(data != NULL);
  82. list_node_t *node = (list_node_t *)osi_calloc(sizeof(list_node_t));
  83. if (!node) {
  84. OSI_TRACE_ERROR("%s osi_calloc failed.\n", __FUNCTION__ );
  85. return false;
  86. }
  87. node->next = prev_node->next;
  88. node->data = data;
  89. prev_node->next = node;
  90. if (list->tail == prev_node) {
  91. list->tail = node;
  92. }
  93. ++list->length;
  94. return true;
  95. }
  96. bool list_prepend(list_t *list, void *data)
  97. {
  98. assert(list != NULL);
  99. assert(data != NULL);
  100. list_node_t *node = (list_node_t *)osi_calloc(sizeof(list_node_t));
  101. if (!node) {
  102. OSI_TRACE_ERROR("%s osi_calloc failed.\n", __FUNCTION__ );
  103. return false;
  104. }
  105. node->next = list->head;
  106. node->data = data;
  107. list->head = node;
  108. if (list->tail == NULL) {
  109. list->tail = list->head;
  110. }
  111. ++list->length;
  112. return true;
  113. }
  114. bool list_append(list_t *list, void *data)
  115. {
  116. assert(list != NULL);
  117. assert(data != NULL);
  118. list_node_t *node = (list_node_t *)osi_calloc(sizeof(list_node_t));
  119. if (!node) {
  120. OSI_TRACE_ERROR("%s osi_calloc failed.\n", __FUNCTION__ );
  121. return false;
  122. }
  123. node->next = NULL;
  124. node->data = data;
  125. if (list->tail == NULL) {
  126. list->head = node;
  127. list->tail = node;
  128. } else {
  129. list->tail->next = node;
  130. list->tail = node;
  131. }
  132. ++list->length;
  133. return true;
  134. }
  135. bool list_remove(list_t *list, void *data)
  136. {
  137. assert(list != NULL);
  138. assert(data != NULL);
  139. if (list_is_empty(list)) {
  140. return false;
  141. }
  142. if (list->head->data == data) {
  143. list_node_t *next = list_free_node(list, list->head);
  144. if (list->tail == list->head) {
  145. list->tail = next;
  146. }
  147. list->head = next;
  148. return true;
  149. }
  150. for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
  151. if (node->data == data) {
  152. prev->next = list_free_node(list, node);
  153. if (list->tail == node) {
  154. list->tail = prev;
  155. }
  156. return true;
  157. }
  158. return false;
  159. }
  160. bool list_delete(list_t *list, void *data)
  161. {
  162. assert(list != NULL);
  163. assert(data != NULL);
  164. if (list_is_empty(list)) {
  165. return false;
  166. }
  167. if (list->head->data == data) {
  168. list_node_t *next = list_delete_node(list, list->head);
  169. if (list->tail == list->head) {
  170. list->tail = next;
  171. }
  172. list->head = next;
  173. return true;
  174. }
  175. for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
  176. if (node->data == data) {
  177. prev->next = list_delete_node(list, node);
  178. if (list->tail == node) {
  179. list->tail = prev;
  180. }
  181. return true;
  182. }
  183. return false;
  184. }
  185. void list_clear(list_t *list)
  186. {
  187. assert(list != NULL);
  188. for (list_node_t *node = list->head; node; ) {
  189. node = list_free_node(list, node);
  190. }
  191. list->head = NULL;
  192. list->tail = NULL;
  193. list->length = 0;
  194. }
  195. list_node_t *list_foreach(const list_t *list, list_iter_cb callback, void *context)
  196. {
  197. assert(list != NULL);
  198. assert(callback != NULL);
  199. for (list_node_t *node = list->head; node; ) {
  200. list_node_t *next = node->next;
  201. if (!callback(node->data, context)) {
  202. return node;
  203. }
  204. node = next;
  205. }
  206. return NULL;
  207. }
  208. list_node_t *list_begin(const list_t *list)
  209. {
  210. assert(list != NULL);
  211. return list->head;
  212. }
  213. list_node_t *list_end(UNUSED_ATTR const list_t *list)
  214. {
  215. assert(list != NULL);
  216. return NULL;
  217. }
  218. list_node_t *list_next(const list_node_t *node)
  219. {
  220. assert(node != NULL);
  221. return node->next;
  222. }
  223. void *list_node(const list_node_t *node)
  224. {
  225. assert(node != NULL);
  226. return node->data;
  227. }
  228. list_node_t *list_free_node(list_t *list, list_node_t *node)
  229. {
  230. assert(list != NULL);
  231. assert(node != NULL);
  232. list_node_t *next = node->next;
  233. if (list->free_cb) {
  234. list->free_cb(node->data);
  235. }
  236. osi_free(node);
  237. --list->length;
  238. return next;
  239. }
  240. // remove the element from list but do not free the node data
  241. list_node_t *list_delete_node(list_t *list, list_node_t *node)
  242. {
  243. assert(list != NULL);
  244. assert(node != NULL);
  245. list_node_t *next = node->next;
  246. osi_free(node);
  247. --list->length;
  248. return next;
  249. }