List.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. empty();
  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 empty() {
  72. clear();
  73. if (start) {
  74. check_pointer(start);
  75. delete start;
  76. }
  77. }
  78. void add(T *data) {
  79. count++;
  80. if (count > 1) {
  81. ListItem<T> *c = start;
  82. while (c->next) {
  83. c = c->next;
  84. }
  85. c->next = new ListItem<T>();
  86. c->next->data = data;
  87. } else {
  88. start = new ListItem<T>();
  89. start->data = data;
  90. }
  91. }
  92. void add_front(T *data) {
  93. count++;
  94. ListItem<T> *c = start;
  95. start = new ListItem<T>();
  96. start->data = data;
  97. start->next = c;
  98. }
  99. void remove(T *data) {
  100. if (!start || !data) return;
  101. ListItem<T> *s = start;
  102. if (s->data == data) {
  103. check_pointer(s->data);
  104. delete s->data;
  105. start = start->next;
  106. count--;
  107. } else {
  108. while (s) {
  109. if (s->next && s->next->data == data) {
  110. auto n = s->next->next;
  111. check_pointer(s->next->data);
  112. check_pointer(s->next);
  113. delete s->next->data;
  114. delete s->next;
  115. s->next = n;
  116. count--;
  117. return;
  118. }
  119. s = s->next;
  120. }
  121. }
  122. }
  123. void soft_remove(T *data) {
  124. if (!start || !data) return;
  125. ListItem<T> *s = start;
  126. if (s->data == data) {
  127. auto tmp = start;
  128. start = start->next;
  129. delete tmp;
  130. count--;
  131. } else {
  132. while (s) {
  133. if (s->next && s->next->data == data) {
  134. auto n = s->next->next;
  135. check_pointer(s->next);
  136. delete s->next;
  137. s->next = n;
  138. count--;
  139. return;
  140. }
  141. s = s->next;
  142. }
  143. }
  144. }
  145. void remove(uint32_t index, uint32_t amount) {
  146. auto *result = splice(index, amount);
  147. delete result;
  148. }
  149. List<T> *splice(uint32_t index, uint32_t amount) {
  150. auto *removedElements = new List<T>();
  151. if (index < count) {
  152. uint32_t m = (index + amount) > count ? count - index : amount;
  153. uint32_t curr_id = 0;
  154. auto s = start;
  155. while (curr_id < index) {
  156. s = s->next;
  157. if (!s) return removedElements;
  158. curr_id++;
  159. }
  160. ListItem<T> *t;
  161. for (uint32_t i = 0; i < m; i++) {
  162. t = s->next;
  163. if (s->data) {
  164. removedElements->add(s->data);
  165. }
  166. delete s;
  167. s = t->next;
  168. count--;
  169. }
  170. if (index == 0) {
  171. start = s;
  172. }
  173. }
  174. return removedElements;
  175. }
  176. T *pop_front() {
  177. if (!start) {
  178. // List is empty, nothing to remove
  179. return nullptr;
  180. }
  181. ListItem<T> *front = start;
  182. start = start->next; // Update the start pointer to the next element
  183. T *data = front->data; // Store the data of the front element
  184. delete front; // Delete the front element
  185. count--;
  186. return data; // Return the data of the removed element
  187. }
  188. T *last() {
  189. if (!start) {
  190. return nullptr;
  191. }
  192. if (!start->next) {
  193. return start->data;
  194. }
  195. ListItem<T> *current = start;
  196. while (current->next) {
  197. current = current->next;
  198. }
  199. return current->data; // Return the data
  200. }
  201. T *pop() {
  202. if (!start) {
  203. // List is empty, nothing to remove
  204. return nullptr;
  205. }
  206. if (!start->next) {
  207. // Only one element in the list
  208. T *data = start->data;
  209. delete start;
  210. start = nullptr;
  211. count--;
  212. return data;
  213. }
  214. ListItem<T> *previous = nullptr;
  215. ListItem<T> *current = start;
  216. while (current->next) {
  217. previous = current;
  218. current = current->next;
  219. }
  220. previous->next = nullptr; // Remove the last element from the list
  221. T *data = current->data; // Store the data of the last element
  222. count--;
  223. delete current; // Delete the last element
  224. return data; // Return the data of the removed element
  225. }
  226. ListIterator<T> begin() {
  227. return ListIterator<T>(start);
  228. }
  229. ListIterator<T> end() {
  230. return ListIterator<T>(nullptr);
  231. }
  232. T *operator[](int i) {
  233. int index = 0;
  234. auto *item = start;
  235. while (item) {
  236. if (index == i) return item->data;
  237. item = item->next;
  238. index++;
  239. }
  240. return nullptr;
  241. }
  242. };