avdl_dynamic_array.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "avdl_dynamic_array.h"
  5. /* Init empty array */
  6. int dd_da_init(struct dd_dynamic_array *da, int el_size) {
  7. /* Init everything to 0, except element size to given value */
  8. da->element_size = el_size;
  9. da->elements = 0;
  10. da->array_size = 0;
  11. da->array = 0;
  12. /* Everything OK */
  13. return 0;
  14. }
  15. /* Init array with specific array size */
  16. int dd_da_inita(struct dd_dynamic_array *da, int el_size, int ar_size) {
  17. /* Init element and array size, and allocate memory
  18. * there are no elements in initialization
  19. */
  20. da->element_size = el_size;
  21. da->elements = 0;
  22. /* create array based on (array_size * element_size) */
  23. da->array_size = ar_size;
  24. da->array = malloc( da->element_size *da->array_size );
  25. /* Check allocation */
  26. if (!da->array) {
  27. fprintf(stderr, "da_inita: cannot allocate memory\n");
  28. return -1;
  29. }
  30. /* Everything OK */
  31. return 0;
  32. }
  33. /* Adds one element (of size element_size) to the array */
  34. int dd_da_add(struct dd_dynamic_array *da, void *data) {
  35. /* first check if array can hold new data, if not
  36. * increase array size, then just add the new element
  37. */
  38. /* No array exists */
  39. if (!da->array) {
  40. /* Init array at 3 elements */
  41. da->array_size = 3;
  42. da->array = malloc(da->element_size *da->array_size);
  43. /* check allocation */
  44. if (!da->array) {
  45. printf("da_add: cannot allocate memory\n");
  46. return -1;
  47. }
  48. } else
  49. /* New element will go over array size */
  50. if (da->elements +1 > da->array_size) {
  51. /* Double array size */
  52. da->array_size *= 2;
  53. void *temp = realloc(da->array, da->element_size *da->array_size);
  54. /* Allocation worked */
  55. if (temp) {
  56. da->array = temp;
  57. }
  58. /* Allocation failed */
  59. else {
  60. printf("error: cannot re-allocate memory, abort\n");
  61. return -1;
  62. }
  63. }
  64. /* Copy element byte-by-byte (according to element_size) to array */
  65. memcpy( ((char*)da->array) +(da->element_size *da->elements),
  66. data, da->element_size);
  67. /* Increment elements */
  68. da->elements++;
  69. /* Return OK */
  70. return 0;
  71. }
  72. /* Adds an array of data to the dynamic array */
  73. int dd_da_adda(struct dd_dynamic_array *da, void *data, unsigned int ar_size) {
  74. /* For each element, try to add it, return on error
  75. * (char*) is used to count 1 byte at a time, this might need fixing later on
  76. */
  77. for (unsigned int i = 0; i < ar_size; i++) {
  78. if (dd_da_add(da, ((char*) data) +(da->element_size *i)) != 0) {
  79. fprintf(stderr, "da_adda: unable to add array of data to dynamic array\n");
  80. return -1;
  81. }
  82. }
  83. return 0;
  84. }
  85. /* Adds one element (of size element_size) to the array */
  86. int dd_da_add_first(struct dd_dynamic_array *da, void *data) {
  87. /* first check if array can hold new data, if not
  88. * increase array size, then just add the new element
  89. */
  90. /* No array exists */
  91. if (!da->array) {
  92. /* Init array at 3 elements */
  93. da->array_size = 3;
  94. da->array = malloc(da->element_size *da->array_size);
  95. /* check allocation */
  96. if (!da->array) {
  97. printf("da_add: cannot allocate memory\n");
  98. return -1;
  99. }
  100. } else
  101. /* New element will go over array size */
  102. if (da->elements +1 > da->array_size) {
  103. /* Double array size */
  104. da->array_size *= 2;
  105. void *temp = realloc(da->array, da->element_size *da->array_size);
  106. /* Allocation worked */
  107. if (temp) {
  108. da->array = temp;
  109. }
  110. /* Allocation failed */
  111. else {
  112. printf("error: cannot re-allocate memory, abort\n");
  113. return -1;
  114. }
  115. }
  116. /* move elements to free first slot */
  117. memmove( ((char*)da->array) +(da->element_size *1),
  118. (char*)da->array, da->element_size *da->elements);
  119. /* Copy element byte-by-byte (according to element_size) to array */
  120. memcpy( (char*)da->array,
  121. data, da->element_size);
  122. /* Increment elements */
  123. da->elements++;
  124. /* Return OK */
  125. return 0;
  126. }
  127. int dd_da_pop(struct dd_dynamic_array *da) {
  128. if (da->elements > 0) {
  129. da->elements--;
  130. if (da->elements < da->array_size/3) {
  131. da->array_size /= 3;
  132. void *ptr;
  133. ptr = realloc(da->array, da->array_size * da->element_size);
  134. if (ptr) {
  135. da->array = ptr;
  136. return 0;
  137. }
  138. return -1;
  139. }
  140. return 0;
  141. }
  142. return -1;
  143. }
  144. int dd_da_remove(struct dd_dynamic_array *da, unsigned int element) {
  145. /* selected element does not exist */
  146. if (element >= da->elements) {
  147. return -1;;
  148. }
  149. /* move elements one step backwards */
  150. unsigned int i = element;
  151. for (i = element+1; i < da->elements; i++) {
  152. memcpy( dd_da_get(da, i-1), dd_da_get(da, i), da->element_size );
  153. }
  154. /* finaly, remove element */
  155. da->elements--;
  156. /* element removed succesfully */
  157. return 0;
  158. }
  159. /* Clean allocated array */
  160. void dd_da_free(struct dd_dynamic_array *da) {
  161. /* if array exists, free it, leaves struct in undefined state */
  162. if (da->array) {
  163. free(da->array);
  164. }
  165. }
  166. /* Get element */
  167. void *dd_da_get(struct dd_dynamic_array *da, unsigned int element) {
  168. if (element >= da->elements) {
  169. printf("dd_da_get: out of bounds error: %d / %d\n", element, da->elements);
  170. exit(-1);
  171. }
  172. return ((char*)da->array) +(element *da->element_size);
  173. }