List.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #pragma once
  2. #include <furi.h>
  3. #include <iterator>
  4. #include "Helpers.h"
  5. template<typename T>
  6. struct ListItem {
  7. ListItem *next;
  8. T *data;
  9. };
  10. template<typename T>
  11. struct ListIterator {
  12. using iterator_category = std::forward_iterator_tag;
  13. ListItem<T> *current;
  14. explicit ListIterator(ListItem<T> *node) : current(node) {}
  15. ListIterator &operator++() {
  16. current = current->next;
  17. return *this;
  18. }
  19. ListIterator operator++(int) {
  20. ListIterator iterator = *this;
  21. ++(*this);
  22. return iterator;
  23. }
  24. bool operator==(const ListIterator &other) const {
  25. return current == other.current;
  26. }
  27. bool operator!=(const ListIterator &other) const {
  28. return current != other.current;
  29. }
  30. T *operator*() const {
  31. return (current->data);
  32. }
  33. T *operator->() const {
  34. return current->data;
  35. }
  36. };
  37. template<typename T>
  38. struct List {
  39. uint32_t count;
  40. ListItem<T> *start = nullptr;
  41. List() : count(0) {}
  42. ~List() {
  43. FURI_LOG_D("App", "List emptied");
  44. clear();
  45. }
  46. void soft_clear() {
  47. auto *item = start;
  48. ListItem<T> *t;
  49. while (item) {
  50. t = item;
  51. item = item->next;
  52. delete t;
  53. }
  54. count = 0;
  55. }
  56. void clear() {
  57. auto *item = start;
  58. ListItem<T> *t;
  59. while (item) {
  60. t = item;
  61. item = item->next;
  62. if (t->data) {
  63. check_pointer(t->data);
  64. delete t->data;
  65. }
  66. check_pointer(t);
  67. delete t;
  68. }
  69. count = 0;
  70. }
  71. void add(T *data) {
  72. check_pointer(data);
  73. count++;
  74. if (count > 1) {
  75. ListItem<T> *c = start;
  76. while (c->next) {
  77. c = c->next;
  78. }
  79. c->next = new ListItem<T>();
  80. c->next->data = data;
  81. } else {
  82. start = new ListItem<T>();
  83. start->data = data;
  84. }
  85. }
  86. void add_front(T *data) {
  87. count++;
  88. ListItem<T> *c = start;
  89. start = new ListItem<T>();
  90. start->data = data;
  91. start->next = c;
  92. }
  93. void remove(T *data) {
  94. if (!start || !data) return;
  95. ListItem<T> *s = start;
  96. if (s->data == data) {
  97. check_pointer(s->data);
  98. delete s->data;
  99. start = start->next;
  100. count--;
  101. } else {
  102. while (s) {
  103. if (s->next && s->next->data == data) {
  104. auto n = s->next->next;
  105. check_pointer(s->next->data);
  106. check_pointer(s->next);
  107. delete s->next->data;
  108. delete s->next;
  109. s->next = n;
  110. count--;
  111. return;
  112. }
  113. s = s->next;
  114. }
  115. }
  116. }
  117. void soft_remove(T *data) {
  118. if (!start || !data) return;
  119. ListItem<T> *s = start;
  120. if (s->data == data) {
  121. auto tmp = start;
  122. start = start->next;
  123. delete tmp;
  124. count--;
  125. } else {
  126. while (s) {
  127. if (s->next && s->next->data == data) {
  128. auto n = s->next->next;
  129. check_pointer(s->next);
  130. delete s->next;
  131. s->next = n;
  132. count--;
  133. return;
  134. }
  135. s = s->next;
  136. }
  137. }
  138. }
  139. void remove(uint32_t index, uint32_t amount) {
  140. auto *result = splice(index, amount);
  141. delete result;
  142. }
  143. List<T> *splice(uint32_t index, uint32_t amount) {
  144. auto *removedElements = new List<T>();
  145. if (index < count) {
  146. uint32_t m = (index + amount) > count ? count - index : amount;
  147. uint32_t curr_id = 0;
  148. auto currentItem = start;
  149. ListItem<T> *prevItem = nullptr;
  150. while (curr_id < index) {
  151. prevItem = currentItem;
  152. currentItem = currentItem->next;
  153. if (!currentItem) return removedElements;
  154. curr_id++;
  155. }
  156. ListItem<T> *temp;
  157. for (uint32_t i = 0; i < m; i++) {
  158. temp = currentItem->next;
  159. if (currentItem->data) {
  160. removedElements->add(currentItem->data);
  161. }
  162. delete currentItem;
  163. currentItem = temp;
  164. count--;
  165. }
  166. if (prevItem) {
  167. prevItem->next = currentItem;
  168. } else {
  169. start = currentItem; // Update start if removing from the beginning.
  170. }
  171. }
  172. return removedElements;
  173. }
  174. T *pop_front() {
  175. if (!start) {
  176. // List is empty, nothing to remove
  177. return nullptr;
  178. }
  179. ListItem<T> *front = start;
  180. start = start->next; // Update the start pointer to the next element
  181. T *data = front->data; // Store the data of the front element
  182. delete front; // Delete the front element
  183. count--;
  184. return data; // Return the data of the removed element
  185. }
  186. T *last() {
  187. if (!start) {
  188. return nullptr;
  189. }
  190. if (!start->next) {
  191. return start->data;
  192. }
  193. ListItem<T> *current = start;
  194. while (current->next) {
  195. current = current->next;
  196. }
  197. return current->data; // Return the data
  198. }
  199. T *pop() {
  200. if (!start) {
  201. FURI_LOG_E("LIST", "No start for pop");
  202. // List is empty, nothing to remove
  203. return nullptr;
  204. }
  205. if (!start->next) {
  206. // Only one element in the list
  207. T *data = start->data;
  208. delete start;
  209. start = nullptr;
  210. count--;
  211. return data;
  212. }
  213. ListItem<T> *previous = nullptr;
  214. ListItem<T> *current = start;
  215. while (current->next) {
  216. previous = current;
  217. current = current->next;
  218. }
  219. previous->next = nullptr; // Remove the last element from the list
  220. T *data = current->data; // Store the data of the last element
  221. count--;
  222. delete current; // Delete the last element
  223. return data; // Return the data of the removed element
  224. }
  225. ListIterator<T> begin() {
  226. return ListIterator<T>(start);
  227. }
  228. ListIterator<T> end() {
  229. return ListIterator<T>(nullptr);
  230. }
  231. T *operator[](int i) {
  232. int index = 0;
  233. auto *item = start;
  234. while (item) {
  235. if (index == i) return item->data;
  236. item = item->next;
  237. index++;
  238. }
  239. return nullptr;
  240. }
  241. };