vec.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #ifndef __sti__vec_h__
  2. #define __sti__vec_h__
  3. // Public Domain.
  4. #include <stddef.h> // size_t
  5. #include <string.h> // memcpy
  6. // -----------------------
  7. // non-thread-safe vectors
  8. // -----------------------
  9. // declare a vector
  10. #define VEC(t) \
  11. struct { \
  12. size_t len, alloc; \
  13. t* data; \
  14. }
  15. // initialisze a vector
  16. #define VEC_INIT(x) \
  17. do { \
  18. (x)->data = NULL; \
  19. (x)->len = 0; \
  20. (x)->alloc = 0; \
  21. } while(0)
  22. // helpers
  23. #define VEC_LEN(x) ((x)->len)
  24. #define VEC_ALLOC(x) ((x)->alloc)
  25. #define VEC_DATA(x) ((x)->data)
  26. #define VEC_ITEM(x, i) (VEC_DATA(x)[(i)])
  27. #define VEC_TAIL(x) (VEC_DATA(x)[VEC_LEN(x)-1])
  28. #define VEC_HEAD(x) (VEC_DATA(x)[0])
  29. #define VEC_FIND(x, ptr_o) vec_find(VEC_DATA(x), VEC_LEN(x), sizeof(*VEC_DATA(x)), ptr_o)
  30. #define VEC_TRUNC(x) (VEC_LEN(x) = 0)
  31. //
  32. #define VEC_GROW(x) vec_resize((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)))
  33. // check if a size increase is needed to insert one more item
  34. #define VEC_CHECK(x) \
  35. do { \
  36. if(VEC_LEN(x) >= VEC_ALLOC(x)) { \
  37. VEC_GROW(x); \
  38. } \
  39. } while(0)
  40. // operations
  41. // increase size and assign the new entry
  42. #define VEC_PUSH(x, e) \
  43. do { \
  44. VEC_CHECK(x); \
  45. VEC_DATA(x)[VEC_LEN(x)] = (e); \
  46. VEC_LEN(x)++; \
  47. } while(0)
  48. // increase size and evaluates to a pointer to it
  49. #define VEC_INC(x) \
  50. ({ \
  51. VEC_CHECK(x); \
  52. VEC_LEN(x)++; \
  53. &VEC_TAIL(x); \
  54. })
  55. // set the size and zero the contents
  56. #define VEC_CALLOC(x, sz) \
  57. do { \
  58. if(VEC_ALLOC(x) < (sz)) { \
  59. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), (sz)); \
  60. } \
  61. VEC_LEN(x) = (sz); \
  62. memset(VEC_DATA(x), 0, sizeof(*VEC_DATA(x)) * (sz)); \
  63. } while(0)
  64. #define VEC_PREPEND(x, e) \
  65. do { \
  66. VEC_CHECK(x); \
  67. memmove( \
  68. VEC_DATA(x) + 1, \
  69. VEC_DATA(x), \
  70. VEC_LEN(x) * sizeof(*VEC_DATA(x)) \
  71. ); \
  72. VEC_DATA(x)[0] = (e); \
  73. VEC_LEN(x)++; \
  74. } while(0)
  75. #define VEC_PEEK(x) VEC_DATA(x)[VEC_LEN(x) - 1]
  76. #define VEC_POP(x, e) \
  77. do { \
  78. if(VEC_LEN(x) > 0) { \
  79. (e) = VEC_PEEK(x); \
  80. VEC_LEN(x)--; \
  81. } \
  82. } while(0)
  83. #define VEC_POP1(x) \
  84. do { \
  85. if(VEC_LEN(x) > 0) { \
  86. VEC_LEN(x)--; \
  87. } \
  88. } while(0)
  89. // ruins order but is O(1). meh.
  90. #define VEC_RM(x, i) \
  91. do { \
  92. if(VEC_LEN(x) < (i)) break; \
  93. VEC_ITEM(x, i) = VEC_PEEK(x); \
  94. VEC_LEN(x)--; \
  95. } while(0)
  96. // preserves order. O(n)
  97. #define VEC_RM_SAFE(x, i) \
  98. do { \
  99. if(VEC_LEN(x) < (i)) break; \
  100. memmove( \
  101. (char*)VEC_DATA(x) + ((i) * sizeof(*VEC_DATA(x))), \
  102. (char*)VEC_DATA(x) + (((i) + 1) * sizeof(*VEC_DATA(x))), \
  103. (VEC_LEN(x) - (i)) * sizeof(*VEC_DATA(x)) \
  104. ); \
  105. VEC_LEN(x)--; \
  106. } while(0)
  107. // ruins order but is O(1). meh.
  108. #define VEC_RM_VAL(x, ptr_o) vec_rm_val((char*)VEC_DATA(x), &VEC_LEN(x), sizeof(*VEC_DATA(x)), ptr_o)
  109. // TODO: vec_set_ins // sorted insert
  110. // TODO: vec_set_rem
  111. // TODO: vec_set_has
  112. // TODO: vec_purge // search and delete of all entries
  113. #define VEC_FREE(x) \
  114. do { \
  115. if(VEC_DATA(x)) free(VEC_DATA(x)); \
  116. VEC_DATA(x) = NULL; \
  117. VEC_LEN(x) = 0; \
  118. VEC_ALLOC(x) = 0; \
  119. } while(0)
  120. #define VEC_COPY(dst, src) vec_copy( \
  121. (char**)&VEC_DATA(dst), (char*)VEC_DATA(src), \
  122. &VEC_ALLOC(dst), VEC_ALLOC(src), \
  123. &VEC_LEN(dst), VEC_LEN(src), \
  124. sizeof(*VEC_DATA(src)))
  125. #define VEC_REVERSE(x) \
  126. do { \
  127. size_t i, j; \
  128. void* tmp = alloca(sizeof(*VEC_DATA(x))); \
  129. for(i = 0, j = VEC_LEN(x); i < j; i++, j--) { \
  130. memcpy(tmp, VEC_DATA(x)[i]); \
  131. memcpy(VEC_DATA(x)[i], VEC_DATA(x)[j]); \
  132. memcpy(VEC_DATA(x)[j], tmp); \
  133. } \
  134. } while(0)
  135. #define VEC_INSERT_AT(x, e, i) \
  136. do { \
  137. VEC_CHECK(x); \
  138. memmove( /* move the rest of x forward */ \
  139. VEC_DATA(x) + (i) + 1, \
  140. VEC_DATA(x) + (i), \
  141. (VEC_LEN(x) - (i)) * sizeof(*VEC_DATA(x)) \
  142. ); \
  143. VEC_DATA(x)[i] = (e); \
  144. } while(0)
  145. #define VEC_SPLICE(x, y, where) \
  146. do { \
  147. if(VEC_ALLOC(x) < VEC_LEN(x) + VEC_LEN(y)) { \
  148. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), VEC_LEN(x) + VEC_LEN(y)); \
  149. } \
  150. \
  151. memmove( /* move the rest of x forward */ \
  152. VEC_DATA(x) + ((where) + VEC_LEN(y)), \
  153. VEC_DATA(x) + (where), \
  154. (VEC_LEN(x) - (where)) * sizeof(*VEC_DATA(x)) \
  155. ); \
  156. memcpy( /* copy y into the space created */ \
  157. VEC_DATA(x) + (where), \
  158. VEC_DATA(y), \
  159. VEC_LEN(y) * sizeof(*VEC_DATA(y)) \
  160. ); \
  161. VEC_LEN(x) += VEC_LEN(y); \
  162. } while(0)
  163. // concatenate y onto the end of x
  164. #define VEC_CAT(x, y) \
  165. do { \
  166. if(VEC_ALLOC(x) < VEC_LEN(x) + VEC_LEN(y)) { \
  167. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), VEC_LEN(x) + VEC_LEN(y)); \
  168. } \
  169. memcpy( \
  170. VEC_DATA(x) + VEC_LEN(x), \
  171. VEC_DATA(y), \
  172. VEC_LEN(y) * sizeof(*VEC_DATA(y)) \
  173. ); \
  174. VEC_LEN(x) += VEC_LEN(y); \
  175. } while(0)
  176. // make some space somewhere
  177. #define VEC_RESERVE(x, len, where) \
  178. do { \
  179. if(VEC_ALLOC(x) < VEC_LEN(x) + (len)) { \
  180. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), VEC_LEN(x) + (len)); \
  181. } \
  182. \
  183. memmove( /* move the rest of x forward */ \
  184. VEC_DATA(x) + (where) + (len), \
  185. VEC_DATA(x) + (where), \
  186. (VEC_LEN(x) - (where)) * sizeof(*VEC_DATA(x)) \
  187. ); \
  188. VEC_LEN(x) += (len); \
  189. } while(0)
  190. // copy data from y into x at where, overwriting existing data in x
  191. // extends x if it would overlap the end
  192. #define VEC_OVERWRITE(x, y, where) \
  193. do { \
  194. if(VEC_ALLOC(x) < VEC_LEN(y) + (where)) { \
  195. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), where + VEC_LEN(y)); \
  196. } \
  197. memcpy( /* copy y into the space created */ \
  198. VEC_DATA(x) + where, \
  199. VEC_DATA(y), \
  200. VEC_LEN(y) * sizeof(*VEC_DATA(y)) \
  201. ); \
  202. VEC_LEN(x) = MAX(VEC_LEN(x), VEC_LEN(y) + (where)); \
  203. } while(0)
  204. #define VEC_SORT(x, fn) \
  205. qsort(VEC_DATA(x), VEC_LEN(x), sizeof(*VEC_DATA(x)), (int(*)(const void*,const void*))fn);
  206. #define VEC_SORT_R(x, fn, s) \
  207. qsort_r(VEC_DATA(x), VEC_LEN(x), sizeof(*VEC_DATA(x)), (int(*)(const void*,const void*,void*))fn, (void*)s);
  208. /*
  209. Loop macro magic
  210. https://www.chiark.greenend.org.uk/~sgtatham/mp/
  211. HashTable obj;
  212. HT_LOOP(&obj, key, char*, val) {
  213. printf("loop: %s, %s", key, val);
  214. }
  215. effective source:
  216. #define HT_LOOP(obj, keyname, valtype, valname)
  217. if(0)
  218. finished: ;
  219. else
  220. for(char* keyname;;) // internal declarations, multiple loops to avoid comma op funny business
  221. for(valtype valname;;)
  222. for(void* iter = NULL ;;)
  223. if(HT_next(obj, iter, &keyname, &valname))
  224. goto main_loop;
  225. else
  226. while(1)
  227. if(1) {
  228. // when the user uses break
  229. goto finished;
  230. }
  231. else
  232. while(1)
  233. if(!HT_next(obj, iter, &keyname, &valname)) {
  234. // normal termination
  235. goto finished;
  236. }
  237. else
  238. main_loop:
  239. // { user block; not in macro }
  240. */
  241. #define VEC__PASTEINNER(a, b) a ## b
  242. #define VEC__PASTE(a, b) VEC__PASTEINNER(a, b)
  243. #define VEC__ITER(key, val) VEC__PASTE(VEC_iter_ ## key ## __ ## val ## __, __LINE__)
  244. #define VEC__FINISHED(key, val) VEC__PASTE(VEC_finished__ ## key ## __ ## val ## __, __LINE__)
  245. #define VEC__MAINLOOP(key, val) VEC__PASTE(VEC_main_loop__ ## key ## __ ## val ## __, __LINE__)
  246. #define VEC_EACH(obj, index, valname) \
  247. if(0) \
  248. VEC__FINISHED(index, val): ; \
  249. else \
  250. for(typeof(*VEC_DATA(obj)) valname ;;) \
  251. for(size_t index = 0;;) \
  252. if(index < VEC_LEN(obj) && (valname = VEC_ITEM(obj, index), 1)) \
  253. goto VEC__MAINLOOP(index, val); \
  254. else \
  255. while(1) \
  256. if(1) { \
  257. goto VEC__FINISHED(index, val); \
  258. } \
  259. else \
  260. while(1) \
  261. if(++index >= VEC_LEN(obj) || (valname = VEC_ITEM(obj, index), 0)) { \
  262. goto VEC__FINISHED(index, val); \
  263. } \
  264. else \
  265. VEC__MAINLOOP(index, val) :
  266. // { user block; not in macro }
  267. // pointer version
  268. #define VEC_EACHP(obj, index, valname) \
  269. if(0) \
  270. VEC__FINISHED(index, val): ; \
  271. else \
  272. for(typeof(*VEC_DATA(obj))* valname ;;) \
  273. for(size_t index = 0;;) \
  274. if(index < VEC_LEN(obj) && (valname = &VEC_ITEM(obj, index), 1)) \
  275. goto VEC__MAINLOOP(index, val); \
  276. else \
  277. while(1) \
  278. if(1) { \
  279. goto VEC__FINISHED(index, val); \
  280. } \
  281. else \
  282. while(1) \
  283. if(++index >= VEC_LEN(obj) || (valname = &VEC_ITEM(obj, index), 0)) { \
  284. goto VEC__FINISHED(index, val); \
  285. } \
  286. else \
  287. VEC__MAINLOOP(index, val) :
  288. // { user block; not in macro }
  289. // reverse
  290. #define VEC_R_EACH(obj, index, valname) \
  291. if(0) \
  292. VEC__FINISHED(index, val): ; \
  293. else \
  294. for(typeof(*VEC_DATA(obj)) valname ;;) \
  295. for(ptrdiff_t index = (ptrdiff_t)VEC_LEN(obj) - 1;;) \
  296. if(index >= 0 && (valname = VEC_ITEM(obj, index), 1)) \
  297. goto VEC__MAINLOOP(index, val); \
  298. else \
  299. while(1) \
  300. if(1) { \
  301. goto VEC__FINISHED(index, val); \
  302. } \
  303. else \
  304. while(1) \
  305. if(--index < 0 || (valname = VEC_ITEM(obj, index), 0)) { \
  306. goto VEC__FINISHED(index, val); \
  307. } \
  308. else \
  309. VEC__MAINLOOP(index, val) :
  310. // { user block; not in macro }
  311. // this version only iterates the index
  312. #define VEC_LOOP(obj, index) \
  313. if(0) \
  314. VEC__FINISHED(index, val): ; \
  315. else \
  316. for(size_t index = 0;;) \
  317. if(index < VEC_LEN(obj)) \
  318. goto VEC__MAINLOOP(index, val); \
  319. else \
  320. while(1) \
  321. if(1) { \
  322. goto VEC__FINISHED(index, val); \
  323. } \
  324. else \
  325. while(1) \
  326. if(++index >= VEC_LEN(obj)) { \
  327. goto VEC__FINISHED(index, val); \
  328. } \
  329. else \
  330. VEC__MAINLOOP(index, val) :
  331. // { user block; not in macro }
  332. // reverse; this version only iterates the index
  333. #define VEC_R_LOOP(obj, index) \
  334. if(0) \
  335. VEC__FINISHED(index, val): ; \
  336. else \
  337. for(ptrdiff_t index = (ptrdiff_t)VEC_LEN(obj) - 1;;) \
  338. if(index >= 0) \
  339. goto VEC__MAINLOOP(index, val); \
  340. else \
  341. while(1) \
  342. if(1) { \
  343. goto VEC__FINISHED(index, val); \
  344. } \
  345. else \
  346. while(1) \
  347. if(--index < 0) { \
  348. goto VEC__FINISHED(index, val); \
  349. } \
  350. else \
  351. VEC__MAINLOOP(index, val) :
  352. // { user block; not in macro }
  353. // Do not use these directly.
  354. void vec_resize(void** data, size_t* size, size_t elem_size);
  355. ptrdiff_t vec_find(void* data, size_t len, size_t stride, void* search);
  356. ptrdiff_t vec_rm_val(char* data, size_t* len, size_t stride, void* search);
  357. void vec_resize_to(void** data, size_t* size, size_t elem_size, size_t new_size);
  358. void vec_copy(
  359. char** dst_data, char* src_data,
  360. size_t* dst_alloc, size_t src_alloc,
  361. size_t* dst_len, size_t src_len,
  362. size_t elem_size
  363. );
  364. #endif // __sti__vec_h__