List.h 6.3 KB

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