list.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #include "list.h"
  2. #include "helpers.h"
  3. List *list_make() {
  4. List *list = malloc(sizeof(List));
  5. if (list != NULL) {
  6. list->head = NULL;
  7. list->tail = NULL;
  8. list->count = 0;
  9. } else {
  10. FURI_LOG_W("LIST", "Failed to create list");
  11. }
  12. return list;
  13. }
  14. void list_free(List *list) {
  15. if (list == NULL) return;
  16. ListItem *start = list->head;
  17. while (start) {
  18. ListItem *next = start->next;
  19. free(start->data);
  20. free(start);
  21. start = next;
  22. }
  23. free(list);
  24. }
  25. void list_free_data(List *list) {
  26. if (list == NULL) return;
  27. ListItem *start = list->head;
  28. while (start) {
  29. ListItem *next = start->next;
  30. free(start->data);
  31. free(start);
  32. start = next;
  33. }
  34. list->head = NULL;
  35. list->tail = NULL;
  36. list->count = 0;
  37. }
  38. void list_clear(List *list) {
  39. if (list == NULL) return;
  40. ListItem *start = list->head;
  41. while (start) {
  42. ListItem *next = start->next;
  43. free(start);
  44. start = next;
  45. }
  46. list->head = NULL;
  47. list->tail = NULL;
  48. list->count = 0;
  49. }
  50. void list_push_back(void *data, List *list) {
  51. if (list == NULL) {
  52. FURI_LOG_W("LIST", "List not initialized, cannot push data");
  53. return;
  54. }
  55. ListItem *newItem = malloc(sizeof(ListItem));
  56. if (newItem != NULL) {
  57. newItem->data = data;
  58. newItem->next = NULL;
  59. newItem->prev = list->tail;
  60. if (list->tail == NULL) {
  61. list->head = newItem;
  62. list->tail = newItem;
  63. } else {
  64. list->tail->next = newItem;
  65. list->tail = newItem;
  66. }
  67. list->count++;
  68. }
  69. }
  70. void list_push_front(void *data, List *list) {
  71. if (list == NULL) {
  72. FURI_LOG_W("LIST", "List not initialized, cannot push data");
  73. return;
  74. }
  75. ListItem *newItem = malloc(sizeof(ListItem));
  76. if (newItem != NULL) {
  77. newItem->data = data;
  78. newItem->next = list->head;
  79. if (list->head == NULL) {
  80. list->head = newItem;
  81. list->tail = newItem;
  82. } else {
  83. list->head->prev = newItem;
  84. list->head = newItem;
  85. }
  86. list->count++;
  87. }
  88. }
  89. void *list_pop_back(List *list) {
  90. if (!check_pointer(list)) {
  91. FURI_LOG_W("LIST", "List not initialized, cannot pop data");
  92. return NULL;
  93. }
  94. if (!check_pointer(list->tail)) {
  95. FURI_LOG_W("LIST", "List empty, cannot pop");
  96. return NULL;
  97. }
  98. void *data = list->tail->data;
  99. check_pointer(data);
  100. ListItem *prev = list->tail->prev;
  101. check_pointer(prev);
  102. if (prev) {
  103. prev->next = NULL;
  104. } else {
  105. list->head = NULL;
  106. }
  107. free(list->tail);
  108. list->tail = prev;
  109. list->count--;
  110. return data;
  111. }
  112. void *list_pop_front(List *list) {
  113. if (!check_pointer(list)) {
  114. FURI_LOG_W("LIST", "List not initialized, cannot pop data");
  115. return NULL;
  116. }
  117. if (!check_pointer(list->head)) {
  118. FURI_LOG_W("LIST", "List empty, cannot pop");
  119. return NULL;
  120. }
  121. void *data = list->head->data;
  122. check_pointer(data);
  123. ListItem *next = list->head->next;
  124. if (next) {
  125. next->prev = NULL;
  126. } else {
  127. list->tail = NULL;
  128. }
  129. free(list->head);
  130. list->head = next;
  131. list->count--;
  132. return data;
  133. }
  134. void *list_pop_at(size_t index, List *list) {
  135. if (!check_pointer(list)) {
  136. FURI_LOG_W("LIST", "List not initialized, cannot pop data");
  137. return NULL;
  138. }
  139. if (index >= list->count) {
  140. FURI_LOG_W("LIST", "Out of range, cannot pop");
  141. return NULL;
  142. }
  143. if (index == 0) {
  144. return list_pop_front(list);
  145. }
  146. if (index == list->count - 1) {
  147. return list_pop_back(list);
  148. }
  149. ListItem *current = list->head;
  150. check_pointer(current);
  151. for (size_t i = 0; i < index; i++) {
  152. current = current->next;
  153. }
  154. check_pointer(current);
  155. void *data = current->data;
  156. check_pointer(data);
  157. current->prev->next = current->next;
  158. current->next->prev = current->prev;
  159. free(current);
  160. list->count--;
  161. return data;
  162. }
  163. void list_remove_item(void *data, List *list) {
  164. if (list == NULL) {
  165. return;
  166. }
  167. ListItem *current = list->head;
  168. while (current != NULL) {
  169. if (current->data == data) {
  170. if (current->prev != NULL) {
  171. current->prev->next = current->next;
  172. } else {
  173. list->head = current->next;
  174. }
  175. if (current->next != NULL) {
  176. current->next->prev = current->prev;
  177. } else {
  178. list->tail = current->prev;
  179. }
  180. free(current);
  181. list->count--;
  182. break;
  183. }
  184. current = current->next;
  185. }
  186. }
  187. void list_remove_at(size_t index, List *list) {
  188. if (list == NULL) {
  189. return;
  190. }
  191. void *d = list_pop_at(index, list);
  192. free(d);
  193. }
  194. List *list_splice(size_t index, size_t count, List *list) {
  195. if (list == NULL) {
  196. FURI_LOG_W("LIST", "List not initialized, cannot splice");
  197. return NULL;
  198. }
  199. List *newList = list_make();
  200. if (index >= list->count || count == 0) {
  201. return newList;
  202. }
  203. if (index == 0 && count >= list->count) {
  204. newList->head = list->head;
  205. newList->tail = list->tail;
  206. newList->count = list->count;
  207. list->head = NULL;
  208. list->tail = NULL;
  209. list->count = 0;
  210. return newList;
  211. }
  212. ListItem *start = list->head;
  213. for (size_t i = 0; i < index; i++) {
  214. start = start->next;
  215. }
  216. size_t c = count;
  217. if (c > list->count) c = list->count - index;
  218. ListItem *end = start;
  219. for (size_t i = 1; i < c && end->next; i++) {
  220. end = end->next;
  221. if (end->next == NULL) c = i;
  222. }
  223. newList->head = start;
  224. newList->tail = end;
  225. newList->count = c;
  226. if (end->next != NULL) {
  227. end->next->prev = start->prev;
  228. } else {
  229. list->tail = start->prev;
  230. }
  231. if (start->prev != NULL) {
  232. start->prev->next = end->next;
  233. } else {
  234. list->head = end->next;
  235. }
  236. start->prev = NULL;
  237. end->next = NULL;
  238. list->count -= c;
  239. return newList;
  240. }
  241. void *list_peek_front(List *list) {
  242. if (list == NULL || list->head == NULL) {
  243. return NULL;
  244. }
  245. return list->head->data;
  246. }
  247. ListItem *list_get_index(List *list, size_t index){
  248. check_pointer(list);
  249. ListItem *curr = list->head;
  250. check_pointer(curr);
  251. if(index > list->count || !curr) return NULL;
  252. for (size_t i = 0; i < index; i++) {
  253. if (!curr) return NULL;
  254. curr = curr->next;
  255. }
  256. return curr;
  257. }
  258. void *list_peek_index(List *list, size_t index) {
  259. ListItem *curr = list_get_index(list,index);
  260. check_pointer(curr);
  261. if(curr) {
  262. check_pointer(curr->data);
  263. return curr->data;
  264. }
  265. return NULL;
  266. }
  267. void *list_peek_back(List *list) {
  268. if (!list || !list->tail) {
  269. return NULL;
  270. }
  271. check_pointer(list->tail->data);
  272. return list->tail->data;
  273. }