DArray.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #ifndef SCUFCONT_DARRAY_H_
  2. #define SCUFCONT_DARRAY_H_
  3. #include <stdbool.h>
  4. #include <stddef.h>
  5. #include <stdlib.h> // IWYU pragma: keep
  6. #include <string.h>
  7. #include "scufcont.h" // IWYU pragma: keep
  8. // #define SCUFCONT_BOUNDS_CHECK
  9. #ifdef SCUFCONT_BOUNDS_CHECK
  10. #include <stdio.h>
  11. #endif // SCUFCONT_BOUNDS_CHECK
  12. #define SCDARRAY_EXPANDER(macro, type, type_name, func_name) macro(type, SCDArray_##type_name, SCDArray_##type_name##_##func_name)
  13. #define SCDARRAY_IMPL(type, type_name) \
  14. SCDARRAY_EXPANDER(SCDARRAY_ALLOC, type, type_name, alloc) \
  15. SCDARRAY_EXPANDER(SCDARRAY_FREE, type, type_name, free) \
  16. SCDARRAY_EXPANDER(SCDARRAY_IS_NULL, type, type_name, is_null) \
  17. SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK, type, type_name, push_back) \
  18. SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_MULTIPLE, type, type_name, push_back_multiple) \
  19. SCDARRAY_EXPANDER(SCDARRAY_AT, type, type_name, at) \
  20. SCDARRAY_EXPANDER(SCDARRAY_RESIZE, type, type_name, resize) \
  21. SCDARRAY_EXPANDER(SCDARRAY_REMOVE_NO_RESIZE, type, type_name, remove_no_resize) \
  22. SCDARRAY_EXPANDER(SCDARRAY_REMOVE, type, type_name, remove) \
  23. SCDARRAY_EXPANDER(SCDARRAY_CLEAR_NO_RESIZE, type, type_name, clear_no_resize) \
  24. SCDARRAY_EXPANDER(SCDARRAY_CLEAR, type, type_name, clear)
  25. #define SCDARRAY_SIGS(type, type_name) \
  26. SCDARRAY_EXPANDER(SCDARRAY_ALLOC_SIG, type, type_name, alloc); \
  27. SCDARRAY_EXPANDER(SCDARRAY_FREE_SIG, type, type_name, free); \
  28. SCDARRAY_EXPANDER(SCDARRAY_IS_NULL_SIG, type, type_name, is_null); \
  29. SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_SIG, type, type_name, push_back); \
  30. SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_MULTIPLE_SIG, type, type_name, push_back_multiple); \
  31. SCDARRAY_EXPANDER(SCDARRAY_AT_SIG, type, type_name, at); \
  32. SCDARRAY_EXPANDER(SCDARRAY_RESIZE_SIG, type, type_name, resize); \
  33. SCDARRAY_EXPANDER(SCDARRAY_REMOVE_SIG, type, type_name, remove); \
  34. SCDARRAY_EXPANDER(SCDARRAY_CLEAR_NO_RESIZE_SIG, type, type_name, clear_no_resize); \
  35. SCDARRAY_EXPANDER(SCDARRAY_CLEAR_SIG, type, type_name, clear);
  36. #define SCDARRAY_HEADER(type, type_name) \
  37. SCDARRAY_STRUCT(type, type_name) \
  38. SCDARRAY_SIGS(type, type_name)
  39. // SCDARRAY_ALLOC_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_alloc);
  40. // SCDARRAY_PUSH_BACK_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_push_back);
  41. #define SCDARRAY_STRUCT(type, type_name) \
  42. typedef struct { \
  43. type *data; \
  44. size_t len; \
  45. size_t capacity; \
  46. } SCDArray_##type_name;
  47. // SCDARRAY_STRUCT(int);
  48. #define SCDARRAY_ALLOC_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr)
  49. /**
  50. @fn SCDArray_alloc
  51. @return SCUFCONT_OUT_OF_MEMORY
  52. @return SCUFCONT_SUCCESS
  53. */
  54. #define SCDARRAY_ALLOC(type, type_name, func_name) \
  55. SCDARRAY_ALLOC_SIG(type, type_name, func_name) { \
  56. darr->data = (type *) calloc(1, sizeof(type)); \
  57. if (darr->data == NULL) { \
  58. return SCUFCONT_OUT_OF_MEMORY; \
  59. } \
  60. darr->len = 0; \
  61. darr->capacity = 1; \
  62. return SCUFCONT_SUCCESS; \
  63. }
  64. #define SCDARRAY_FREE_SIG(type, type_name, func_name) void func_name(type_name *const darr)
  65. #define SCDARRAY_FREE(type, type_name, func_name) \
  66. SCDARRAY_FREE_SIG(type, type_name, func_name) { \
  67. free(darr->data); \
  68. }
  69. #define SCDARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const type_name *const darr)
  70. #define SCDARRAY_IS_NULL(type, type_name, func_name) \
  71. SCDARRAY_IS_NULL_SIG(type, type_name, func_name) { \
  72. return darr->data == NULL; \
  73. }
  74. // SCDARRAY_ALLOC(int, SCDArray_int, SCDArray_int_alloc);
  75. #define SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr, const type *const new_elem)
  76. /**
  77. @fn SCDArray_push_back
  78. @return SCUFCONT_OUT_OF_MEMORY
  79. @return SCUFCONT_SUCCESS
  80. */
  81. #define SCDARRAY_PUSH_BACK(type, type_name, func_name) \
  82. SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) { \
  83. if (darr->len + 1 > darr->capacity) { \
  84. darr->capacity *= 2; \
  85. darr->data = (type *) realloc(darr->data, darr->capacity * sizeof(*new_elem)); \
  86. if (darr->data == NULL) { \
  87. return SCUFCONT_OUT_OF_MEMORY; \
  88. } \
  89. } \
  90. memcpy(darr->data + darr->len, new_elem, sizeof(*new_elem)); \
  91. darr->len++; \
  92. return SCUFCONT_SUCCESS; \
  93. }
  94. #define SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr, const type *const new_elems, const size_t new_elems_n)
  95. /**
  96. @fn SCDArray_push_back_multiple
  97. @return SCUFCONT_OUT_OF_MEMORY
  98. @return SCUFCONT_SUCCESS
  99. */
  100. #define SCDARRAY_PUSH_BACK_MULTIPLE(type, type_name, func_name) \
  101. SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) { \
  102. if (darr->len + new_elems_n > darr->capacity) { \
  103. darr->data = (type *) realloc(darr->data, (darr->capacity + new_elems_n) * sizeof(type)); \
  104. if (darr->data == NULL) { \
  105. return SCUFCONT_OUT_OF_MEMORY; \
  106. } \
  107. darr->capacity += new_elems_n; \
  108. } \
  109. memcpy(darr->data + darr->len, new_elems, sizeof(type) * new_elems_n); \
  110. darr->len += new_elems_n; \
  111. return SCUFCONT_SUCCESS; \
  112. }
  113. // SCDARRAY_PUSH_BACK_MULTIPLE(int, SCDArray_int, SCDArray_int_push_back_multiple)
  114. #define SCDARRAY_AT_SIG(type, type_name, func_name) type *func_name(const type_name *const darr, const size_t i)
  115. // SCDARRAY_PUSH_BACK(int, SCDArray_int, SCDArray_int_push_back);
  116. #ifdef SCUFCONT_BOUNDS_CHECK
  117. #define SCDARRAY_AT(type, type_name, func_name) \
  118. SCDARRAY_AT_SIG(type, type_name, func_name) { \
  119. if (i < 0 || i > darr->len) { \
  120. fprintf(stderr, #func_name " out-of-bounds. i: %zu, len: %zu", i, darr->len); \
  121. exit(1); \
  122. } \
  123. \
  124. return darr->data + i; \
  125. }
  126. #else
  127. #define SCDARRAY_AT(type, type_name, func_name) \
  128. SCDARRAY_AT_SIG(type, type_name, func_name) { \
  129. return darr->data + i; \
  130. }
  131. #endif // SCUFCONT_BOUNDS_CHECK
  132. // SCDARRAY_AT(char*, SCDArray_charp, SCDArray_charp_at)
  133. #define SCDARRAY_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr)
  134. #define SCDARRAY_RESIZE(type, type_name, func_name) \
  135. SCDARRAY_RESIZE_SIG(type, type_name, func_name) { \
  136. if (darr->len == 0) { \
  137. darr->data = realloc(darr->data, sizeof(type)); \
  138. } else { \
  139. darr->data = realloc(darr->data, sizeof(type) * darr->len); \
  140. } \
  141. }
  142. #define SCDARRAY_REMOVE_NO_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr, const size_t i)
  143. #define SCDARRAY_REMOVE_NO_RESIZE(type, type_name, func_name) \
  144. SCDARRAY_REMOVE_SIG(type, type_name, func_name) { \
  145. if (i != darr->len - 1) { \
  146. memmove(darr->data + i, darr->data + i + 1, (darr->len - (i + 1)) * sizeof(type)); \
  147. } \
  148. darr->len--; \
  149. }
  150. // SCDARRAY_EXPANDER(SCDARRAY_REMOVE_NO_RESIZE, char*, charp, remove_no_resize)
  151. #define SCDARRAY_REMOVE_SIG(type, type_name, func_name) void func_name(type_name *const darr, const size_t i)
  152. #define SCDARRAY_REMOVE(type, type_name, func_name) \
  153. SCDARRAY_REMOVE_SIG(type, type_name, func_name) { \
  154. type_name##_remove_no_resize(darr, i); \
  155. type_name##_resize(darr); \
  156. }
  157. // SCDARRAY_EXPANDER(SCDARRAY_REMOVE, char*, charp, remove)
  158. #define SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr)
  159. #define SCDARRAY_CLEAR_NO_RESIZE(type, type_name, func_name) \
  160. SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) { \
  161. darr->len = 0; \
  162. }
  163. // SCDARRAY_CLEAR_NO_RESIZE(char*, SCDArray_charp, SCDArray_charp_clear_no_resize)
  164. #define SCDARRAY_CLEAR_SIG(type, type_name, func_name) void func_name(type_name *const darr)
  165. #define SCDARRAY_CLEAR(type, type_name, func_name) \
  166. SCDARRAY_CLEAR_SIG(type, type_name, func_name) { \
  167. type_name##_clear_no_resize(darr); \
  168. type_name##_resize(darr); \
  169. }
  170. // SCDARRAY_EXPANDER(SCDARRAY_CLEAR, char*, charp, clear)
  171. #endif // SCUFCONT_DARRAY_H_