Advertisement
Guest User

Untitled

a guest
Sep 4th, 2015
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.86 KB | None | 0 0
  1. #ifndef LIST_H
  2. #define LIST_H
  3.  
  4. #include <stdbool.h>
  5. #include <stdlib.h>
  6.  
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10.  
  11. typedef struct list_t list_t;
  12.  
  13. /***************************************************************************
  14. * Allocates the new, empty list with initial capacity. *
  15. ***************************************************************************/
  16. list_t* list_t_alloc(size_t initial_capacity);
  17.  
  18. /***************************************************************************
  19. * Inserts the element to in front of the head of the list. Returns true if *
  20. * operation was successful. *
  21. ***************************************************************************/
  22. bool list_t_push_front(list_t* p_list, void* p_element);
  23.  
  24. /***************************************************************************
  25. * Appends the element to the tail of the list. Returns true if operation *
  26. * was successful. *
  27. ***************************************************************************/
  28. bool list_t_push_back(list_t* p_list, void* p_element);
  29.  
  30. /***************************************************************************
  31. * Inserts the element into the list before index'th element. Returns true *
  32. * if operation was successful. *
  33. ***************************************************************************/
  34. bool list_t_insert(list_t* p_list, size_t index, void* p_element);
  35.  
  36. /***************************************************************************
  37. * Returns the amount of elements stored in the list. *
  38. ***************************************************************************/
  39. size_t list_t_size(list_t* p_list);
  40.  
  41. /***************************************************************************
  42. * Returns the index'th element of the list. Returns NULL if the index is *
  43. * out of range. *
  44. ***************************************************************************/
  45. void* list_t_get(list_t* p_list, size_t index);
  46.  
  47. /***************************************************************************
  48. * Sets the index'th element of the list. Returns the old value. If the *
  49. * index is out of range, returns NULL. *
  50. ***************************************************************************/
  51. void* list_t_set(list_t* p_list, size_t index, void* p_new_value);
  52.  
  53. /***************************************************************************
  54. * Removes and returns the front element of the list. If list is empty, *
  55. * returns NULL. *
  56. ***************************************************************************/
  57. void* list_t_pop_front(list_t* p_list);
  58.  
  59. /***************************************************************************
  60. * Removes and returns the last element of the list. If list is empty, *
  61. * returns NULL. *
  62. ***************************************************************************/
  63. void* list_t_pop_back(list_t* p_list);
  64.  
  65. /***************************************************************************
  66. * Removes the element at index 'index' from the list and returns the *
  67. * it. If the list is empty or the index is out of range, returns NULL. *
  68. ***************************************************************************/
  69. void* list_t_remove_at(list_t* p_list, size_t index);
  70.  
  71. /***************************************************************************
  72. * Returns true if the list contains the specified element using the *
  73. * equality function. Returns false otherwise. *
  74. ***************************************************************************/
  75. bool list_t_contains(list_t* p_list,
  76. void* p_element,
  77. bool (*p_equals_function)(void*, void*));
  78.  
  79. /***************************************************************************
  80. * Clears this list. The client programmer is responsible for memory- *
  81. * managing the contents. *
  82. ***************************************************************************/
  83. void list_t_clear(list_t* p_list);
  84.  
  85. /***************************************************************************
  86. * Clears and deallocates the list. *
  87. ***************************************************************************/
  88. void list_t_free(list_t* p_list);
  89.  
  90. #ifdef __cplusplus
  91. }
  92. #endif
  93.  
  94. #endif /* LIST_H */
  95.  
  96. #include "list.h"
  97. #include <stdbool.h>
  98. #include <stdlib.h>
  99.  
  100. typedef struct list_t {
  101. void** p_table;
  102. size_t size;
  103. size_t capacity;
  104. size_t head;
  105. size_t mask;
  106. } list_t;
  107.  
  108. static const size_t MINIMUM_CAPACITY = 16;
  109.  
  110. static size_t max(size_t a, size_t b)
  111. {
  112. return a < b ? b : a;
  113. }
  114.  
  115. static size_t fix_initial_capacity(size_t initial_capacity)
  116. {
  117. size_t ret = 1;
  118.  
  119. initial_capacity = max(initial_capacity, MINIMUM_CAPACITY);
  120.  
  121. while (ret < initial_capacity) ret <<= 1;
  122.  
  123. return ret;
  124. }
  125.  
  126. list_t* list_t_alloc(size_t initial_capacity)
  127. {
  128. list_t* p_ret = malloc(sizeof(*p_ret));
  129.  
  130. if (!p_ret) return NULL;
  131.  
  132. initial_capacity = fix_initial_capacity(initial_capacity);
  133.  
  134. p_ret->p_table = malloc(sizeof(void*) * initial_capacity);
  135.  
  136. if (!p_ret->p_table)
  137. {
  138. free(p_ret);
  139. return NULL;
  140. }
  141.  
  142. p_ret->capacity = initial_capacity;
  143. p_ret->mask = initial_capacity - 1;
  144. p_ret->head = 0;
  145. p_ret->size = 0;
  146.  
  147. return p_ret;
  148. }
  149.  
  150. static bool ensure_capacity_before_add(list_t* p_list)
  151. {
  152. void** p_new_table;
  153. size_t i;
  154. size_t new_capacity;
  155.  
  156. if (p_list->size < p_list->capacity) return true;
  157.  
  158. new_capacity = 2 * p_list->capacity;
  159. p_new_table = malloc(sizeof(void*) * new_capacity);
  160.  
  161. if (!p_new_table) return false;
  162.  
  163. for (i = 0; i < p_list->size; ++i)
  164. {
  165. p_new_table[i] = p_list->p_table[(p_list->head + i) & p_list->mask];
  166. }
  167.  
  168. free(p_list->p_table);
  169. p_list->p_table = p_new_table;
  170. p_list->capacity = new_capacity;
  171. p_list->mask = new_capacity - 1;
  172. p_list->head = 0;
  173.  
  174. return true;
  175. }
  176.  
  177. bool list_t_push_front(list_t* p_list, void* p_element)
  178. {
  179. if (!p_list) return false;
  180. if (!ensure_capacity_before_add(p_list)) return false;
  181.  
  182. p_list->head = (p_list->head - 1) & p_list->mask;
  183. p_list->p_table[p_list->head] = p_element;
  184. p_list->size++;
  185. return true;
  186. }
  187.  
  188. bool list_t_push_back(list_t* p_list, void* p_element)
  189. {
  190. if (!p_list) return false;
  191. if (!ensure_capacity_before_add(p_list)) return false;
  192.  
  193. p_list->p_table[(p_list->head + p_list->size) & p_list->mask] = p_element;
  194. p_list->size++;
  195. return true;
  196. }
  197.  
  198. bool list_t_insert(list_t* p_list, size_t index, void* p_element)
  199. {
  200. size_t elements_before;
  201. size_t elements_after;
  202. size_t i;
  203. size_t head;
  204. size_t mask;
  205. size_t size;
  206.  
  207. if (!p_list) return false;
  208. if (!ensure_capacity_before_add(p_list)) return false;
  209. if (index > p_list->size) return false;
  210.  
  211. elements_before = index;
  212. elements_after = p_list->size - index;
  213. head = p_list->head;
  214. mask = p_list->mask;
  215. size = p_list->size;
  216.  
  217. if (elements_before < elements_after)
  218. {
  219. /* Move preceding elements one position to the left. */
  220. for (i = 0; i < elements_before; ++i)
  221. {
  222. p_list->p_table[(head + i - 1) & mask] =
  223. p_list->p_table[(head + i) & mask];
  224. }
  225.  
  226. head = (head - 1) & mask;
  227. p_list->p_table[(head + index) & mask] = p_element;
  228. p_list->head = head;
  229. }
  230. else
  231. {
  232. /* Move the following elements one position to the right. */
  233. for (i = 0; i < elements_after; ++i)
  234. {
  235. p_list->p_table[(head + size - i) & mask] =
  236. p_list->p_table[(head + size - i - 1) & mask];
  237. }
  238.  
  239. p_list->p_table[(head + index) & mask] = p_element;
  240. }
  241.  
  242. p_list->size++;
  243. return true;
  244. }
  245.  
  246. size_t list_t_size(list_t* p_list)
  247. {
  248. return p_list ? p_list->size : 0;
  249. }
  250.  
  251. void* list_t_get(list_t* p_list, size_t index)
  252. {
  253. if (!p_list) return NULL;
  254. if (index >= p_list->size) return NULL;
  255.  
  256. return p_list->p_table[(p_list->head + index) & p_list->mask];
  257. }
  258.  
  259. void* list_t_set(list_t* p_list, size_t index, void* p_new_value)
  260. {
  261. void* p_ret;
  262.  
  263. if (!p_list) return NULL;
  264. if (index >= p_list->size) return NULL;
  265.  
  266. p_ret = p_list->p_table[(p_list->head + index) & p_list->mask];
  267. p_list->p_table[(p_list->head + index) & p_list->mask] = p_new_value;
  268. return p_ret;
  269. }
  270.  
  271. void* list_t_pop_front(list_t* p_list)
  272. {
  273. void* p_ret;
  274.  
  275. if (!p_list) return NULL;
  276. if (p_list->size == 0) return NULL;
  277.  
  278. p_ret = p_list->p_table[p_list->head];
  279. p_list->head++;
  280. p_list->size--;
  281. return p_ret;
  282. }
  283.  
  284. void* list_t_pop_back(list_t* p_list)
  285. {
  286. void* p_ret;
  287.  
  288. if (!p_list) return NULL;
  289. if (p_list->size == 0) return NULL;
  290.  
  291. p_ret = p_list->p_table[(p_list->head + p_list->size - 1) & p_list->mask];
  292. p_list->size--;
  293. return p_ret;
  294. }
  295.  
  296. void* list_t_remove_at(list_t* p_list, size_t index)
  297. {
  298. void* p_ret;
  299. size_t head;
  300. size_t mask;
  301. size_t elements_before;
  302. size_t elements_after;
  303. size_t i;
  304. size_t j;
  305.  
  306. if (!p_list) return NULL;
  307. if (index >= p_list->size) return NULL;
  308.  
  309. head = p_list->head;
  310. mask = p_list->mask;
  311.  
  312. p_ret = p_list->p_table[(head + index) & mask];
  313.  
  314. elements_before = index;
  315. elements_after = p_list->size - index - 1;
  316.  
  317. if (elements_before < elements_after)
  318. {
  319. /* Move the preceding elements one position to the right. */
  320. for (i = 0, j = elements_before; i < elements_before; ++i, --j)
  321. {
  322. p_list->p_table[(head + j) & mask] =
  323. p_list->p_table[(head + j - 1) & mask];
  324. }
  325.  
  326. p_list->head = (head + 1) & mask;
  327. }
  328. else
  329. {
  330. /* Move the following elements one position to the left. */
  331. for (i = 0; i < elements_after; ++i)
  332. {
  333. p_list->p_table[(head + index + i) & mask] =
  334. p_list->p_table[(head + index + i + 1) & mask];
  335. }
  336. }
  337.  
  338. p_list->size--;
  339. return p_ret;
  340. }
  341.  
  342. bool list_t_contains(list_t* p_list,
  343. void* p_element,
  344. bool (*p_equals_function)(void*, void*))
  345. {
  346. size_t i;
  347.  
  348. if (!p_list) return false;
  349. if (!p_equals_function) return false;
  350.  
  351. for (i = 0; i < p_list->size; ++i)
  352. {
  353. if (p_equals_function(p_element,
  354. p_list->p_table[(p_list->head + i) &
  355. p_list->mask]))
  356. {
  357. return true;
  358. }
  359. }
  360.  
  361. return false;
  362. }
  363.  
  364. void list_t_clear(list_t* p_list)
  365. {
  366. if (!p_list) return;
  367.  
  368. p_list->head = 0;
  369. p_list->size = 0;
  370. }
  371.  
  372. void list_t_free(list_t* p_list)
  373. {
  374. if (!p_list) return;
  375.  
  376. free(p_list->p_table);
  377. free(p_list);
  378. }
  379.  
  380. p_list->head++;
  381.  
  382. p_list->head = (p_list->head + 1) & p_list->mask;
  383.  
  384. /* Move the preceding elements one position to the right. */
  385. for (i = 0, j = elements_before; i < elements_before; ++i, --j)
  386. {
  387. p_list->p_table[(head + j) & mask] =
  388. p_list->p_table[(head + j - 1) & mask];
  389. }
  390.  
  391. /* Move the preceding elements one position to the right. */
  392. for (j = elements_before; j > 0; --j)
  393. {
  394. p_list->p_table[(head + j) & mask] =
  395. p_list->p_table[(head + j - 1) & mask];
  396. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement