cvector.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* https://github.com/eteran/c-vector */
  2. #ifndef CVECTOR_H_
  3. #define CVECTOR_H_
  4. #include <assert.h> /* for assert */
  5. #include <stdlib.h> /* for malloc/realloc/free */
  6. /**
  7. * @brief cvector_vector_type - The vector type used in this library
  8. */
  9. #define cvector_vector_type(type) type *
  10. /**
  11. * @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector
  12. * @param vec - the vector
  13. * @param size - the new capacity to set
  14. * @return void
  15. */
  16. #define cvector_set_capacity(vec, size) \
  17. do { \
  18. if (vec) { \
  19. ((size_t *)(vec))[-1] = (size); \
  20. } \
  21. } while (0)
  22. /**
  23. * @brief cvector_set_size - For internal use, sets the size variable of the vector
  24. * @param vec - the vector
  25. * @param size - the new capacity to set
  26. * @return void
  27. */
  28. #define cvector_set_size(vec, size) \
  29. do { \
  30. if (vec) { \
  31. ((size_t *)(vec))[-2] = (size); \
  32. } \
  33. } while (0)
  34. /**
  35. * @brief cvector_capacity - gets the current capacity of the vector
  36. * @param vec - the vector
  37. * @return the capacity as a size_t
  38. */
  39. #define cvector_capacity(vec) \
  40. ((vec) ? ((size_t *)(vec))[-1] : (size_t)0)
  41. /**
  42. * @brief cvector_size - gets the current size of the vector
  43. * @param vec - the vector
  44. * @return the size as a size_t
  45. */
  46. #define cvector_size(vec) \
  47. ((vec) ? ((size_t *)(vec))[-2] : (size_t)0)
  48. /**
  49. * @brief cvector_empty - returns non-zero if the vector is empty
  50. * @param vec - the vector
  51. * @return non-zero if empty, zero if non-empty
  52. */
  53. #define cvector_empty(vec) \
  54. (cvector_size(vec) == 0)
  55. /**
  56. * @brief cvector_grow - For internal use, ensures that the vector is at least <count> elements big
  57. * @param vec - the vector
  58. * @param count - the new capacity to set
  59. * @return void
  60. */
  61. #define cvector_grow(vec, count) \
  62. do { \
  63. const size_t cv_sz = (count) * sizeof(*(vec)) + (sizeof(size_t) * 2); \
  64. if (!(vec)) { \
  65. size_t *cv_p = malloc(cv_sz); \
  66. assert(cv_p); \
  67. (vec) = (void *)(&cv_p[2]); \
  68. cvector_set_capacity((vec), (count)); \
  69. cvector_set_size((vec), 0); \
  70. } else { \
  71. size_t *cv_p1 = &((size_t *)(vec))[-2]; \
  72. size_t *cv_p2 = realloc(cv_p1, (cv_sz)); \
  73. assert(cv_p2); \
  74. (vec) = (void *)(&cv_p2[2]); \
  75. cvector_set_capacity((vec), (count)); \
  76. } \
  77. } while (0)
  78. /**
  79. * @brief cvector_pop_back - removes the last element from the vector
  80. * @param vec - the vector
  81. * @return void
  82. */
  83. #define cvector_pop_back(vec) \
  84. do { \
  85. cvector_set_size((vec), cvector_size(vec) - 1); \
  86. } while (0)
  87. /**
  88. * @brief cvector_erase - removes the element at index i from the vector
  89. * @param vec - the vector
  90. * @param i - index of element to remove
  91. * @return void
  92. */
  93. #define cvector_erase(vec, i) \
  94. do { \
  95. if (vec) { \
  96. const size_t cv_sz = cvector_size(vec); \
  97. if ((i) < cv_sz) { \
  98. cvector_set_size((vec), cv_sz - 1); \
  99. size_t cv_x; \
  100. for (cv_x = (i); cv_x < (cv_sz - 1); ++cv_x) { \
  101. (vec)[cv_x] = (vec)[cv_x + 1]; \
  102. } \
  103. } \
  104. } \
  105. } while (0)
  106. /**
  107. * @brief cvector_free - frees all memory associated with the vector
  108. * @param vec - the vector
  109. * @return void
  110. */
  111. #define cvector_free(vec) \
  112. do { \
  113. if (vec) { \
  114. size_t *p1 = &((size_t *)(vec))[-2]; \
  115. free(p1); \
  116. } \
  117. } while (0)
  118. /**
  119. * @brief cvector_begin - returns an iterator to first element of the vector
  120. * @param vec - the vector
  121. * @return a pointer to the first element (or NULL)
  122. */
  123. #define cvector_begin(vec) \
  124. (vec)
  125. /**
  126. * @brief cvector_end - returns an iterator to one past the last element of the vector
  127. * @param vec - the vector
  128. * @return a pointer to one past the last element (or NULL)
  129. */
  130. #define cvector_end(vec) \
  131. ((vec) ? &((vec)[cvector_size(vec)]) : NULL)
  132. /* user request to use logarithmic growth algorithm */
  133. #ifdef CVECTOR_LOGARITHMIC_GROWTH
  134. /**
  135. * @brief cvector_push_back - adds an element to the end of the vector
  136. * @param vec - the vector
  137. * @param value - the value to add
  138. * @return void
  139. */
  140. #define cvector_push_back(vec, value) \
  141. do { \
  142. size_t cv_cap = cvector_capacity(vec); \
  143. if (cv_cap <= cvector_size(vec)) { \
  144. cvector_grow((vec), !cv_cap ? cv_cap + 1 : cv_cap * 2); \
  145. } \
  146. vec[cvector_size(vec)] = (value); \
  147. cvector_set_size((vec), cvector_size(vec) + 1); \
  148. } while (0)
  149. #else
  150. /**
  151. * @brief cvector_push_back - adds an element to the end of the vector
  152. * @param vec - the vector
  153. * @param value - the value to add
  154. * @return void
  155. */
  156. #define cvector_push_back(vec, value) \
  157. do { \
  158. size_t cv_cap = cvector_capacity(vec); \
  159. if (cv_cap <= cvector_size(vec)) { \
  160. cvector_grow((vec), cv_cap + 1); \
  161. } \
  162. vec[cvector_size(vec)] = (value); \
  163. cvector_set_size((vec), cvector_size(vec) + 1); \
  164. } while (0)
  165. #endif /* CVECTOR_LOGARITHMIC_GROWTH */
  166. /**
  167. * @brief cvector_copy - copy a vector
  168. * @param from - the original vector
  169. * @param to - destination to which the function copy to
  170. * @return void
  171. */
  172. #define cvector_copy(from, to) \
  173. do { \
  174. for(size_t i = 0; i < cvector_size(from); i++) { \
  175. cvector_push_back(to, from[i]); \
  176. } \
  177. } while (0) \
  178. #endif /* CVECTOR_H_ */