fork(1) download
  1. // Hidden header style array. (2.00)
  2.  
  3. #include <assert.h>
  4. #include <stddef.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8.  
  9. // Utility.
  10.  
  11. #define MAX(a, b) \
  12. ({ __auto_type _x = (a); __auto_type _y = (b); \
  13.   (_y > _x) ? _y : _x; })
  14.  
  15. // Array (private).
  16.  
  17. typedef struct {
  18. size_t size, capacity;
  19. } _Header;
  20.  
  21. #define _PTR_TO_HDR(p) ((_Header*)((char*)p - sizeof(_Header)))
  22. #define _HDR_TO_PTR(p) ((void*)((char*)p + sizeof(_Header)))
  23.  
  24. void *_ar_reserve(void *p, size_t capacity, size_t itemsize)
  25. {
  26. assert(p != 0);
  27. _Header *self = _PTR_TO_HDR(p);
  28.  
  29. if (capacity > self->capacity)
  30. {
  31. self = realloc(self, sizeof *self + capacity*itemsize);
  32. assert(self != 0);
  33. self->capacity = capacity;
  34. }
  35. return _HDR_TO_PTR(self);
  36. }
  37.  
  38. void *_ar_resize(void *p, size_t size, size_t itemsize)
  39. {
  40. assert(p != 0);
  41. p = _ar_reserve(p, size, itemsize);
  42. _PTR_TO_HDR(p)->size = size;
  43. return p;
  44. }
  45.  
  46. void _ar_free(void *p)
  47. {
  48. if (p != 0)
  49. free(_PTR_TO_HDR(p));
  50. }
  51.  
  52. void *_ar_init(void)
  53. {
  54. _Header *self = malloc(sizeof *self);
  55. assert(self != 0);
  56. self->size = 0;
  57. self->capacity = 0;
  58. return _HDR_TO_PTR(self);
  59. }
  60.  
  61. const void *_ar_at_c(const void *p, ptrdiff_t i, size_t itemsize)
  62. {
  63. assert(p != 0);
  64. ptrdiff_t size = _PTR_TO_HDR(p)->size;
  65. if (i < 0)
  66. i += size;
  67. assert(0 <= i && i < size);
  68. return (const char*)p + i*itemsize;
  69. }
  70.  
  71. void *_ar_at(void *p, ptrdiff_t i, size_t itemsize)
  72. {
  73. return (void*)_ar_at_c(p, i, itemsize);
  74. }
  75.  
  76. void _ar_remove(void *p, size_t i, size_t n, size_t itemsize)
  77. {
  78. assert(p != 0);
  79. _Header *self = _PTR_TO_HDR(p);
  80.  
  81. assert(self->size >= i);
  82. assert(self->size >= i + n);
  83.  
  84. if (n != 0)
  85. {
  86. size_t oldsize = self->size;
  87. size_t j = i + n;
  88.  
  89. if (oldsize > j)
  90. memmove(_ar_at(p, i, itemsize), _ar_at(p, j, itemsize), (oldsize - j)*itemsize);
  91. self->size = oldsize - n;
  92. }
  93. }
  94.  
  95. void *_ar_insert(void *p, size_t i, const void *first, size_t n, size_t itemsize)
  96. {
  97. assert(p != 0);
  98. _Header *self = _PTR_TO_HDR(p);
  99.  
  100. assert(self->size >= i);
  101.  
  102. if (n != 0)
  103. {
  104. size_t oldsize = self->size;
  105. size_t newsize = oldsize + n;
  106.  
  107. if (newsize > self->capacity)
  108. {
  109. p = _ar_reserve(p, MAX(2*self->capacity, newsize), itemsize);
  110. self = _PTR_TO_HDR(p);
  111. }
  112. self->size = newsize;
  113. void *ip = _ar_at(p, i, itemsize);
  114.  
  115. if (oldsize > i)
  116. memmove(_ar_at(p, i + n, itemsize), ip, (oldsize - i)*itemsize);
  117. memcpy(ip, first, n*itemsize);
  118. }
  119. return p;
  120. }
  121.  
  122. void *_ar_append(void *p, const void *item, size_t itemsize)
  123. {
  124. assert(p != 0);
  125. return _ar_insert(p, _PTR_TO_HDR(p)->size, item, 1, itemsize);
  126. }
  127.  
  128. // Array (public).
  129.  
  130. void ar_pop(void *p)
  131. {
  132. assert(p != 0);
  133. _Header *self = _PTR_TO_HDR(p);
  134. assert(self->size > 0);
  135. self->size--;
  136. }
  137.  
  138. void ar_clear(void *p)
  139. {
  140. assert(p != 0);
  141. _PTR_TO_HDR(p)->size = 0;
  142. }
  143.  
  144. size_t ar_size(const void *p)
  145. {
  146. assert(p != 0);
  147. return _PTR_TO_HDR(p)->size;
  148. }
  149.  
  150. size_t ar_capacity(const void *p)
  151. {
  152. assert(p != 0);
  153. return _PTR_TO_HDR(p)->capacity;
  154. }
  155.  
  156. #define ar_init(a) ((a) = _ar_init())
  157. #define ar_free(a) (_ar_free(a), (a) = 0)
  158. #define ar_reserve(a, n) ((a) = _ar_reserve(a, n, sizeof *(a)))
  159. #define ar_resize(a, n) ((a) = _ar_resize(a, n, sizeof *(a)))
  160. #define ar_at(a, i) (((__typeof__(*(a))*)_ar_at(a, i, sizeof *(a)))[0])
  161. #define ar_at_c(a, i) (((const __typeof__(*(a))*)_ar_at_c(a, i, sizeof *(a)))[0])
  162. #define ar_remove(a, i, n) _ar_remove(a, i, n, sizeof *(a))
  163. #define ar_insert(a, i, s, n) ((a) = _ar_insert(a, i, s, n, sizeof *(a)))
  164. #define ar_append(a, v) ((a) = _ar_append(a, (__typeof__(*(a))[]){v}, sizeof *(a)))
  165.  
  166. // Main.
  167.  
  168. void ar_print(const int *p)
  169. {
  170. printf("size;capacity: %zu;%zu: [", ar_size(p), ar_capacity(p));
  171. for (size_t i = 0; i < ar_size(p); i++)
  172. {
  173. if (i != 0) printf(", ");
  174. printf("%d", p[i]);
  175. }
  176. puts("]");
  177. }
  178.  
  179. int main(void)
  180. {
  181. int *p = 0;
  182. // Init
  183. ar_init(p);
  184. ar_print(p);
  185. // Append
  186. for (int i = 0; i < 4; i++)
  187. {
  188. ar_append(p, i);
  189. ar_print(p);
  190. }
  191. // At
  192. for (int i = 0; i < 4; i++)
  193. {
  194. assert(p[i] == ar_at(p, i));
  195. assert(p[ar_size(p)-1-i] == ar_at(p, -1-i));
  196. }
  197. // Insert/Remove
  198. ar_insert(p, 2, ((int[]){1111, 2222}), 2); // middle
  199. ar_print(p);
  200. ar_remove(p, 2, 2);
  201. ar_print(p);
  202. ar_insert(p, 0, ((int[]){-3, -2, -1}), 3); // front
  203. ar_print(p);
  204. ar_remove(p, 0, 3);
  205. ar_print(p);
  206. ar_insert(p, ar_size(p), ((int[]){5, 6, 7, 8}), 4); // back
  207. ar_print(p);
  208. ar_remove(p, ar_size(p)-4, 4);
  209. ar_print(p);
  210. // Pop
  211. while (ar_size(p) != 0)
  212. {
  213. ar_pop(p);
  214. ar_print(p);
  215. }
  216. // Free
  217. ar_free(p);
  218. return 0;
  219. }
Success #stdin #stdout 0s 5308KB
stdin
Standard input is empty
stdout
size;capacity: 0;0: []
size;capacity: 1;1: [0]
size;capacity: 2;2: [0, 1]
size;capacity: 3;4: [0, 1, 2]
size;capacity: 4;4: [0, 1, 2, 3]
size;capacity: 6;8: [0, 1, 1111, 2222, 2, 3]
size;capacity: 4;8: [0, 1, 2, 3]
size;capacity: 7;8: [-3, -2, -1, 0, 1, 2, 3]
size;capacity: 4;8: [0, 1, 2, 3]
size;capacity: 8;8: [0, 1, 2, 3, 5, 6, 7, 8]
size;capacity: 4;8: [0, 1, 2, 3]
size;capacity: 3;8: [0, 1, 2]
size;capacity: 2;8: [0, 1]
size;capacity: 1;8: [0]
size;capacity: 0;8: []