generic_list.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * Copyright 2018-2019 NXP
  3. * All rights reserved.
  4. *
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. /*! *********************************************************************************
  9. *************************************************************************************
  10. * Include
  11. *************************************************************************************
  12. ********************************************************************************** */
  13. #include "generic_list.h"
  14. static list_status_t LIST_Error_Check(list_handle_t list, list_element_handle_t newElement)
  15. {
  16. list_status_t listStatus = kLIST_Ok;
  17. list_element_handle_t element = list->head;
  18. if ((list->max != 0U) && (list->max == list->size))
  19. {
  20. listStatus = kLIST_Full; /*List is full*/
  21. }
  22. else
  23. {
  24. while (element != NULL) /*Scan list*/
  25. {
  26. /* Determine if element is duplicated */
  27. if (element == newElement)
  28. {
  29. listStatus = kLIST_DuplicateError;
  30. break;
  31. }
  32. element = element->next;
  33. }
  34. }
  35. return listStatus;
  36. }
  37. /*! *********************************************************************************
  38. *************************************************************************************
  39. * Public functions
  40. *************************************************************************************
  41. ********************************************************************************** */
  42. /*! *********************************************************************************
  43. * \brief Initialises the list descriptor.
  44. *
  45. * \param[in] list - LIST_ handle to init.
  46. * max - Maximum number of elements in list. 0 for unlimited.
  47. *
  48. * \return void.
  49. *
  50. * \pre
  51. *
  52. * \post
  53. *
  54. * \remarks
  55. *
  56. ********************************************************************************** */
  57. void LIST_Init(list_handle_t list, uint32_t max)
  58. {
  59. list->head = NULL;
  60. list->tail = NULL;
  61. list->max = (uint16_t)max;
  62. list->size = 0;
  63. }
  64. /*! *********************************************************************************
  65. * \brief Gets the list that contains the given element.
  66. *
  67. * \param[in] element - Handle of the element.
  68. *
  69. * \return NULL if element is orphan.
  70. * Handle of the list the element is inserted into.
  71. *
  72. * \pre
  73. *
  74. * \post
  75. *
  76. * \remarks
  77. *
  78. ********************************************************************************** */
  79. list_handle_t LIST_GetList(list_element_handle_t element)
  80. {
  81. return element->list;
  82. }
  83. /*! *********************************************************************************
  84. * \brief Links element to the tail of the list.
  85. *
  86. * \param[in] list - ID of list to insert into.
  87. * element - element to add
  88. *
  89. * \return kLIST_Full if list is full.
  90. * kLIST_Ok if insertion was successful.
  91. *
  92. * \pre
  93. *
  94. * \post
  95. *
  96. * \remarks
  97. *
  98. ********************************************************************************** */
  99. list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t element)
  100. {
  101. uint32_t regPrimask = DisableGlobalIRQ();
  102. list_status_t listStatus = kLIST_Ok;
  103. listStatus = LIST_Error_Check(list, element);
  104. if (listStatus == kLIST_Ok) /* Avoiding list status error */
  105. {
  106. if (list->size == 0U)
  107. {
  108. list->head = element;
  109. }
  110. else
  111. {
  112. list->tail->next = element;
  113. }
  114. #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
  115. #else
  116. element->prev = list->tail;
  117. #endif
  118. element->list = list;
  119. element->next = NULL;
  120. list->tail = element;
  121. list->size++;
  122. }
  123. EnableGlobalIRQ(regPrimask);
  124. return listStatus;
  125. }
  126. /*! *********************************************************************************
  127. * \brief Links element to the head of the list.
  128. *
  129. * \param[in] list - ID of list to insert into.
  130. * element - element to add
  131. *
  132. * \return kLIST_Full if list is full.
  133. * kLIST_Ok if insertion was successful.
  134. *
  135. * \pre
  136. *
  137. * \post
  138. *
  139. * \remarks
  140. *
  141. ********************************************************************************** */
  142. list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t element)
  143. {
  144. uint32_t regPrimask = DisableGlobalIRQ();
  145. list_status_t listStatus = kLIST_Ok;
  146. listStatus = LIST_Error_Check(list, element);
  147. if (listStatus == kLIST_Ok) /* Avoiding list status error */
  148. {
  149. /* Links element to the head of the list */
  150. if (list->size == 0U)
  151. {
  152. list->tail = element;
  153. }
  154. #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
  155. #else
  156. else
  157. {
  158. list->head->prev = element;
  159. }
  160. element->prev = NULL;
  161. #endif
  162. element->list = list;
  163. element->next = list->head;
  164. list->head = element;
  165. list->size++;
  166. }
  167. EnableGlobalIRQ(regPrimask);
  168. return listStatus;
  169. }
  170. /*! *********************************************************************************
  171. * \brief Unlinks element from the head of the list.
  172. *
  173. * \param[in] list - ID of list to remove from.
  174. *
  175. * \return NULL if list is empty.
  176. * ID of removed element(pointer) if removal was successful.
  177. *
  178. * \pre
  179. *
  180. * \post
  181. *
  182. * \remarks
  183. *
  184. ********************************************************************************** */
  185. list_element_handle_t LIST_RemoveHead(list_handle_t list)
  186. {
  187. list_element_handle_t element;
  188. uint32_t regPrimask = DisableGlobalIRQ();
  189. if ((NULL == list) || (list->size == 0U))
  190. {
  191. element = NULL; /*LIST_ is empty*/
  192. }
  193. else
  194. {
  195. element = list->head;
  196. list->size--;
  197. if (list->size == 0U)
  198. {
  199. list->tail = NULL;
  200. }
  201. #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
  202. #else
  203. else
  204. {
  205. element->next->prev = NULL;
  206. }
  207. #endif
  208. element->list = NULL;
  209. list->head = element->next; /*Is NULL if element is head*/
  210. }
  211. EnableGlobalIRQ(regPrimask);
  212. return element;
  213. }
  214. /*! *********************************************************************************
  215. * \brief Gets head element ID.
  216. *
  217. * \param[in] list - ID of list.
  218. *
  219. * \return NULL if list is empty.
  220. * ID of head element if list is not empty.
  221. *
  222. * \pre
  223. *
  224. * \post
  225. *
  226. * \remarks
  227. *
  228. ********************************************************************************** */
  229. list_element_handle_t LIST_GetHead(list_handle_t list)
  230. {
  231. return list->head;
  232. }
  233. /*! *********************************************************************************
  234. * \brief Gets next element ID.
  235. *
  236. * \param[in] element - ID of the element.
  237. *
  238. * \return NULL if element is tail.
  239. * ID of next element if exists.
  240. *
  241. * \pre
  242. *
  243. * \post
  244. *
  245. * \remarks
  246. *
  247. ********************************************************************************** */
  248. list_element_handle_t LIST_GetNext(list_element_handle_t element)
  249. {
  250. return element->next;
  251. }
  252. /*! *********************************************************************************
  253. * \brief Gets previous element ID.
  254. *
  255. * \param[in] element - ID of the element.
  256. *
  257. * \return NULL if element is head.
  258. * ID of previous element if exists.
  259. *
  260. * \pre
  261. *
  262. * \post
  263. *
  264. * \remarks
  265. *
  266. ********************************************************************************** */
  267. list_element_handle_t LIST_GetPrev(list_element_handle_t element)
  268. {
  269. #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
  270. return NULL;
  271. #else
  272. return element->prev;
  273. #endif
  274. }
  275. /*! *********************************************************************************
  276. * \brief Unlinks an element from its list.
  277. *
  278. * \param[in] element - ID of the element to remove.
  279. *
  280. * \return kLIST_OrphanElement if element is not part of any list.
  281. * kLIST_Ok if removal was successful.
  282. *
  283. * \pre
  284. *
  285. * \post
  286. *
  287. * \remarks
  288. *
  289. ********************************************************************************** */
  290. list_status_t LIST_RemoveElement(list_element_handle_t element)
  291. {
  292. list_status_t listStatus = kLIST_Ok;
  293. uint32_t regPrimask = DisableGlobalIRQ();
  294. if (element->list == NULL)
  295. {
  296. listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/
  297. }
  298. else
  299. {
  300. #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
  301. list_element_handle_t element_list = element->list->head;
  302. while (element_list)
  303. {
  304. if (element->list->head == element)
  305. {
  306. element->list->head = element_list->next;
  307. break;
  308. }
  309. if (element_list->next == element)
  310. {
  311. element_list->next = element->next;
  312. break;
  313. }
  314. element_list = element_list->next;
  315. }
  316. #else
  317. if (element->prev == NULL) /*Element is head or solo*/
  318. {
  319. element->list->head = element->next; /*is null if solo*/
  320. }
  321. if (element->next == NULL) /*Element is tail or solo*/
  322. {
  323. element->list->tail = element->prev; /*is null if solo*/
  324. }
  325. if (element->prev != NULL) /*Element is not head*/
  326. {
  327. element->prev->next = element->next;
  328. }
  329. if (element->next != NULL) /*Element is not tail*/
  330. {
  331. element->next->prev = element->prev;
  332. }
  333. #endif
  334. element->list->size--;
  335. element->list = NULL;
  336. }
  337. EnableGlobalIRQ(regPrimask);
  338. return listStatus;
  339. }
  340. /*! *********************************************************************************
  341. * \brief Links an element in the previous position relative to a given member
  342. * of a list.
  343. *
  344. * \param[in] element - ID of a member of a list.
  345. * newElement - new element to insert before the given member.
  346. *
  347. * \return kLIST_OrphanElement if element is not part of any list.
  348. * kLIST_Full if list is full.
  349. * kLIST_Ok if insertion was successful.
  350. *
  351. * \pre
  352. *
  353. * \post
  354. *
  355. * \remarks
  356. *
  357. ********************************************************************************** */
  358. list_status_t LIST_AddPrevElement(list_element_handle_t element, list_element_handle_t newElement)
  359. {
  360. list_status_t listStatus = kLIST_Ok;
  361. uint32_t regPrimask = DisableGlobalIRQ();
  362. if (element->list == NULL)
  363. {
  364. listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/
  365. }
  366. else
  367. {
  368. listStatus = LIST_Error_Check(element->list, newElement);
  369. if (listStatus == kLIST_Ok)
  370. {
  371. #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
  372. list_element_handle_t element_list = element->list->head;
  373. while (element_list)
  374. {
  375. if ((element_list->next == element) || (element_list == element))
  376. {
  377. if (element_list == element)
  378. {
  379. element->list->head = newElement;
  380. }
  381. else
  382. {
  383. element_list->next = newElement;
  384. }
  385. newElement->list = element->list;
  386. newElement->next = element;
  387. element->list->size++;
  388. break;
  389. }
  390. element_list = element_list->next;
  391. }
  392. #else
  393. if (element->prev == NULL) /*Element is list head*/
  394. {
  395. element->list->head = newElement;
  396. }
  397. else
  398. {
  399. element->prev->next = newElement;
  400. }
  401. newElement->list = element->list;
  402. element->list->size++;
  403. newElement->next = element;
  404. newElement->prev = element->prev;
  405. element->prev = newElement;
  406. #endif
  407. }
  408. }
  409. EnableGlobalIRQ(regPrimask);
  410. return listStatus;
  411. }
  412. /*! *********************************************************************************
  413. * \brief Gets the current size of a list.
  414. *
  415. * \param[in] list - ID of the list.
  416. *
  417. * \return Current size of the list.
  418. *
  419. * \pre
  420. *
  421. * \post
  422. *
  423. * \remarks
  424. *
  425. ********************************************************************************** */
  426. uint32_t LIST_GetSize(list_handle_t list)
  427. {
  428. return list->size;
  429. }
  430. /*! *********************************************************************************
  431. * \brief Gets the number of free places in the list.
  432. *
  433. * \param[in] list - ID of the list.
  434. *
  435. * \return Available size of the list.
  436. *
  437. * \pre
  438. *
  439. * \post
  440. *
  441. * \remarks
  442. *
  443. ********************************************************************************** */
  444. uint32_t LIST_GetAvailableSize(list_handle_t list)
  445. {
  446. return ((uint32_t)list->max - (uint32_t)list->size); /*Gets the number of free places in the list*/
  447. }