ds.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. #ifndef __DS_H__
  2. #define __DS_H__
  3. #include <stdint.h>
  4. #include <malloc.h>
  5. #include <string.h>
  6. #include <stdatomic.h>
  7. #include <pthread.h>
  8. // patch for old versions of glibc
  9. #ifndef qsort_r
  10. typedef int (*__compar_d_fn_t) (const void *, const void *, void *);
  11. void ___patch_quicksort_r (void *const pbase, size_t total_elems, size_t size, __compar_d_fn_t cmp, void *arg);
  12. #define qsort_r ___patch_quicksort_r
  13. #endif
  14. // -----------------------
  15. // non-thread-safe vectors
  16. // -----------------------
  17. // declare a vector
  18. #define VEC(t) \
  19. struct { \
  20. size_t len, alloc; \
  21. t* data; \
  22. }
  23. // initialisze a vector
  24. #define VEC_INIT(x) \
  25. do { \
  26. (x)->data = NULL; \
  27. (x)->len = 0; \
  28. (x)->alloc = 0; \
  29. } while(0)
  30. // helpers
  31. #define VEC_LEN(x) ((x)->len)
  32. #define VEC_ALLOC(x) ((x)->alloc)
  33. #define VEC_DATA(x) ((x)->data)
  34. #define VEC_ITEM(x, i) (VEC_DATA(x)[(i)])
  35. #define VEC_TAIL(x) (VEC_DATA(x)[VEC_LEN(x)-1])
  36. #define VEC_HEAD(x) (VEC_DATA(x)[0])
  37. #define VEC_FIND(x, ptr_o) vec_find(VEC_DATA(x), VEC_LEN(x), sizeof(*VEC_DATA(x)), ptr_o)
  38. #define VEC_TRUNC(x) (VEC_LEN(x) = 0)
  39. //
  40. #define VEC_GROW(x) vec_resize((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)))
  41. // check if a size increase is needed to insert one more item
  42. #define VEC_CHECK(x) \
  43. do { \
  44. if(VEC_LEN(x) >= VEC_ALLOC(x)) { \
  45. VEC_GROW(x); \
  46. } \
  47. } while(0)
  48. // operations
  49. // increase size and assign the new entry
  50. #define VEC_PUSH(x, e) \
  51. do { \
  52. VEC_CHECK(x); \
  53. VEC_DATA(x)[VEC_LEN(x)] = (e); \
  54. VEC_LEN(x)++; \
  55. } while(0)
  56. // increase size but don't assign
  57. #define VEC_INC(x) \
  58. do { \
  59. VEC_CHECK(x); \
  60. VEC_LEN(x)++; \
  61. } while(0)
  62. #define VEC_PEEK(x) VEC_DATA(x)[VEC_LEN(x) - 1]
  63. #define VEC_POP(x, e) \
  64. do { \
  65. VEC_CHECK(x); \
  66. (e) = VEC_PEEK(x); \
  67. VEC_LEN(x)--; \
  68. } while(0)
  69. #define VEC_POP1(x) \
  70. do { \
  71. VEC_CHECK(x); \
  72. VEC_LEN(x)--; \
  73. } while(0)
  74. // ruins order but is O(1). meh.
  75. #define VEC_RM(x, i) \
  76. do { \
  77. if(VEC_LEN(x) < (i)) break; \
  78. VEC_ITEM(x, i) = VEC_PEEK(x); \
  79. VEC_LEN(x)--; \
  80. } while(0)
  81. // preserves order. O(n)
  82. #define VEC_RM_SAFE(x, i) \
  83. do { \
  84. if(VEC_LEN(x) < (i)) break; \
  85. memmove( \
  86. VEC_DATA(x) + ((i) * sizeof(*VEC_DATA(x))), \
  87. VEC_DATA(x) + (((i) + 1) * sizeof(*VEC_DATA(x))), \
  88. VEC_LEN(x) - (((i) - 1) * sizeof(*VEC_DATA(x))) \
  89. ); \
  90. VEC_LEN(x)--; \
  91. } while(0)
  92. // TODO: vec_set_ins // sorted insert
  93. // TODO: vec_set_rem
  94. // TODO: vec_set_has
  95. // TODO: vec_purge // search and delete of all entries
  96. #define VEC_FREE(x) \
  97. do { \
  98. if(VEC_DATA(x)) free(VEC_DATA(x)); \
  99. VEC_DATA(x) = NULL; \
  100. VEC_LEN(x) = 0; \
  101. VEC_ALLOC(x) = 0; \
  102. } while(0)
  103. #define VEC_COPY(copy, orig) \
  104. do { \
  105. void* tmp; \
  106. tmp = realloc(VEC_DATA(copy), VEC_ALLOC(orig) * sizeof(*VEC_DATA(orig)) ); \
  107. if(!tmp) { \
  108. fprintf(stderr, "Out of memory in vector copy"); \
  109. return; \
  110. } \
  111. \
  112. VEC_DATA(copy) = tmp; \
  113. VEC_LEN(copy) = VEC_LEN(orig); \
  114. VEC_ALLOC(copy) = VEC_ALLOC(orig); \
  115. \
  116. memcpy(VEC_DATA(copy), VEC_DATA(orig), VEC_LEN(orig) * sizeof(*VEC_DATA(orig))); \
  117. } while(0)
  118. #define VEC_REVERSE(x) \
  119. do { \
  120. size_t i, j; \
  121. void* tmp = alloca(sizeof(*VEC_DATA(x))); \
  122. for(i = 0, j = VEC_LEN(x); i < j; i++, j--) { \
  123. memcpy(tmp, VEC_DATA(x)[i]); \
  124. memcpy(VEC_DATA(x)[i], VEC_DATA(x)[j]); \
  125. memcpy(VEC_DATA(x)[j], tmp); \
  126. } \
  127. } while(0)
  128. #define VEC_SPLICE(x, y, where) \
  129. do { \
  130. if(VEC_ALLOC(x) < VEC_LEN(x) + VEC_LEN(y)) { \
  131. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), VEC_LEN(x) + VEC_LEN(y)); \
  132. } \
  133. \
  134. memcpy( /* move the rest of x forward */ \
  135. VEC_DATA(x) + where + VEC_LEN(y), \
  136. VEC_DATA(x) + where, \
  137. (VEC_LEN(x) - where) * sizeof(*VEC_DATA(x)) \
  138. ); \
  139. memcpy( /* copy y into the space created */ \
  140. VEC_DATA(x) + where, \
  141. VEC_DATA(y), \
  142. VEC_LEN(y) * sizeof(*VEC_DATA(y)) \
  143. ); \
  144. VEC_LEN(x) += VEC_LEN(y); \
  145. } while(0)
  146. // make some space somewhere
  147. #define VEC_RESERVE(x, len, where) \
  148. do { \
  149. if(VEC_ALLOC(x) < VEC_LEN(x) + (len)) { \
  150. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), VEC_LEN(x) + (len)); \
  151. } \
  152. \
  153. memmove( /* move the rest of x forward */ \
  154. VEC_DATA(x) + (where) + (len), \
  155. VEC_DATA(x) + (where), \
  156. (VEC_LEN(x) - (where)) * sizeof(*VEC_DATA(x)) \
  157. ); \
  158. VEC_LEN(x) += (len); \
  159. } while(0)
  160. // copy data from y into x at where, overwriting existing data in x
  161. // extends x if it would overlap the end
  162. #define VEC_OVERWRITE(x, y, where) \
  163. do { \
  164. if(VEC_ALLOC(x) < VEC_LEN(y) + (where)) { \
  165. vec_resize_to((void**)&VEC_DATA(x), &VEC_ALLOC(x), sizeof(*VEC_DATA(x)), where + VEC_LEN(y)); \
  166. } \
  167. memcpy( /* copy y into the space created */ \
  168. VEC_DATA(x) + where, \
  169. VEC_DATA(y), \
  170. VEC_LEN(y) * sizeof(*VEC_DATA(y)) \
  171. ); \
  172. VEC_LEN(x) = MAX(VEC_LEN(x), VEC_LEN(y) + (where)); \
  173. } while(0)
  174. #define VEC_SORT(x, fn) \
  175. qsort(VEC_DATA(x), VEC_LEN(x), sizeof(*VEC_DATA(x)), (void*)fn);
  176. #define VEC_SORT_R(x, fn, s) \
  177. qsort_r(VEC_DATA(x), VEC_LEN(x), sizeof(*VEC_DATA(x)), (__compar_d_fn_t)fn, (void*)s);
  178. /*
  179. Loop macro magic
  180. https://www.chiark.greenend.org.uk/~sgtatham/mp/
  181. HashTable obj;
  182. HT_LOOP(&obj, key, char*, val) {
  183. printf("loop: %s, %s", key, val);
  184. }
  185. effective source:
  186. #define HT_LOOP(obj, keyname, valtype, valname)
  187. if(0)
  188. finished: ;
  189. else
  190. for(char* keyname;;) // internal declarations, multiple loops to avoid comma op funny business
  191. for(valtype valname;;)
  192. for(void* iter = NULL ;;)
  193. if(HT_next(obj, iter, &keyname, &valname))
  194. goto main_loop;
  195. else
  196. while(1)
  197. if(1) {
  198. // when the user uses break
  199. goto finished;
  200. }
  201. else
  202. while(1)
  203. if(!HT_next(obj, iter, &keyname, &valname)) {
  204. // normal termination
  205. goto finished;
  206. }
  207. else
  208. main_loop:
  209. // { user block; not in macro }
  210. */
  211. #define VEC__PASTEINNER(a, b) a ## b
  212. #define VEC__PASTE(a, b) VEC__PASTEINNER(a, b)
  213. #define VEC__ITER(key, val) VEC__PASTE(VEC_iter_ ## key ## __ ## val ## __, __LINE__)
  214. #define VEC__FINISHED(key, val) VEC__PASTE(VEC_finished__ ## key ## __ ## val ## __, __LINE__)
  215. #define VEC__MAINLOOP(key, val) VEC__PASTE(VEC_main_loop__ ## key ## __ ## val ## __, __LINE__)
  216. #define VEC_EACH(obj, index, valname) \
  217. if(0) \
  218. VEC__FINISHED(index, val): ; \
  219. else \
  220. for(typeof(*VEC_DATA(obj)) valname ;;) \
  221. for(size_t index = 0;;) \
  222. if(index < VEC_LEN(obj) && (valname = VEC_ITEM(obj, index), 1)) \
  223. goto VEC__MAINLOOP(index, val); \
  224. else \
  225. while(1) \
  226. if(1) { \
  227. goto VEC__FINISHED(index, val); \
  228. } \
  229. else \
  230. while(1) \
  231. if(++index >= VEC_LEN(obj) || (valname = VEC_ITEM(obj, index), 0)) { \
  232. goto VEC__FINISHED(index, val); \
  233. } \
  234. else \
  235. VEC__MAINLOOP(index, val) :
  236. // { user block; not in macro }
  237. // this version only iterates the index
  238. #define VEC_LOOP(obj, index) \
  239. if(0) \
  240. VEC__FINISHED(index, val): ; \
  241. else \
  242. for(size_t index = 0;;) \
  243. if(index < VEC_LEN(obj)) \
  244. goto VEC__MAINLOOP(index, val); \
  245. else \
  246. while(1) \
  247. if(1) { \
  248. goto VEC__FINISHED(index, val); \
  249. } \
  250. else \
  251. while(1) \
  252. if(++index >= VEC_LEN(obj)) { \
  253. goto VEC__FINISHED(index, val); \
  254. } \
  255. else \
  256. VEC__MAINLOOP(index, val) :
  257. // { user block; not in macro }
  258. void vec_resize(void** data, size_t* size, size_t elem_size);
  259. ptrdiff_t vec_find(void* data, size_t len, size_t stride, void* search);
  260. void vec_resize_to(void** data, size_t* size, size_t elem_size, size_t new_size);
  261. /*********************************
  262. Linked Lists
  263. **********************************
  264. minimal struct signature:
  265. typedef struct Link {
  266. struct Link* next;
  267. struct Link* prev;
  268. } Link;
  269. typedef struct List {
  270. Link* head;
  271. Link* tail;
  272. int length;
  273. } List;
  274. these macros are not perfect. they create temporary variables and should not be nested.
  275. */
  276. #define LIST_DECL(type, prop) \
  277. typedef struct type ## _Link { \
  278. struct type ## _Link *next, *prev; \
  279. type prop; \
  280. } type ## _Link; \
  281. typedef struct type ## _List { \
  282. struct type ## _Link *head, *tail; \
  283. int length; \
  284. } type ## _List;
  285. #define LIST_INIT(list) \
  286. (list)->head = NULL; \
  287. (list)->tail = NULL; \
  288. (list)->length = 0;
  289. #define LIST_APPEND(list, prop, x) \
  290. do { \
  291. typeof((list)->head) __new_link = calloc(1, sizeof(*__new_link)); \
  292. __new_link->prev = (list)->tail; \
  293. if(__new_link->prev) __new_link->prev->next = __new_link; \
  294. (list)->tail = __new_link; \
  295. if((list)->head == NULL) (list)->head = __new_link; \
  296. __new_link->prop = (x); \
  297. (list)->length++; \
  298. } while(0);
  299. #define LIST_PREPEND(list, prop, x) \
  300. do { \
  301. typeof((list)->head) __new_link = calloc(1, sizeof(*__new_link)); \
  302. __new_link->next = (list)->head; \
  303. if(__new_link->next) __new_link->next->prev = __new_link; \
  304. (list)->head = __new_link; \
  305. if((list)->tail == NULL) (list)->tail = __new_link; \
  306. __new_link->prop = x; \
  307. (list)->length++; \
  308. } while(0);
  309. #define LIST_INS_AFTER(list, exist, prop, x) \
  310. do { \
  311. typeof((list)->head) __new_link = calloc(1, sizeof(*__new_link)); \
  312. __new_link->next = (exist)->next; \
  313. __new_link->prev = exist; \
  314. (exist)->next = __new_link; \
  315. if(__new_link->next) __new_link->next->prev = __new_link; \
  316. if((list)->tail == (exist)) (list)->tail = __new_link; \
  317. __new_link->prop = x; \
  318. } while(0);
  319. #define LIST_REMOVE(list, link) \
  320. do { \
  321. typeof((list)->head) __link = (link); \
  322. if((__link) == (list)->head) (list)->head = (__link)->next; \
  323. if((__link) == (list)->tail) (list)->tail = (__link)->prev; \
  324. if((__link)->prev) (__link)->prev->next = (__link)->next; \
  325. if((__link)->next) (__link)->next->prev = (__link)->prev; \
  326. free(__link); \
  327. (list)->length = (list)->length == 0 ? 0 : (list)->length - 1; \
  328. } while(0);
  329. // allows for cyclic iteration
  330. #define LIST_NEXT_LOOP(list, link) \
  331. ((link)->next ? (link)->next : (list)->head)
  332. #define LIST_PREV_LOOP(list, link) \
  333. ((link)->prev ? (link)->prev : (list)->tail)
  334. // concat or copy a list
  335. #define LIST_CONCAT(src, dest) \
  336. do { \
  337. typeof((src)->head) __link = (src)->head; \
  338. while(__link) { \
  339. typeof((src)->head) __new_link = calloc(1, sizeof(*__new_link)); \
  340. memcpy(__new_link, __link, sizeof(*__link)); \
  341. __new_link->next = NULL; \
  342. __new_link->prev = (dest)->tail; \
  343. if((dest)->tail) (dest)->tail->next = __new_link; \
  344. if((dest)->head == NULL) (dest)->head = __new_link; \
  345. (dest)->tail = __new_link; \
  346. (dest)->length++; \
  347. __link = __link->next; \
  348. } \
  349. } while(0);
  350. // does not create a new list from the output
  351. #define LIST_MAP(list, fn) \
  352. do { \
  353. typeof((list)->head) __link = (list)->head; \
  354. while(__link) { \
  355. (fn)(__link); \
  356. __link = __link->next; \
  357. } \
  358. } while(0);
  359. #define LIST_FREE(list) \
  360. do { \
  361. typeof((list)->head) __link = (list)->head; \
  362. while(__link) { \
  363. typeof((list)->head) __tmp = __link; \
  364. __link = __link->next; \
  365. free(__tmp); \
  366. } \
  367. (list)->head = NULL; \
  368. (list)->tail = NULL; \
  369. (list)->length = 0; \
  370. } while(0);
  371. #define LIST__PASTEINNER(a, b) a ## b
  372. #define LIST__PASTE(a, b) LIST__PASTEINNER(a, b)
  373. #define LIST__FINISHED(iter) LIST__PASTE(LIST_finished__ ## iter ## __, __LINE__)
  374. #define LIST__MAINLOOP(iter) LIST__PASTE(LIST_main_loop__ ## iter ## __, __LINE__)
  375. #define LIST_LOOP(list, iter) \
  376. if(0) \
  377. LIST__FINISHED(iter): ; \
  378. else \
  379. for(typeof((list)->head) iter = (list)->head;;) \
  380. if(iter != NULL) \
  381. goto LIST__MAINLOOP(iter); \
  382. else \
  383. while(1) \
  384. if(1) { \
  385. goto LIST__FINISHED(iter); \
  386. } \
  387. else \
  388. while(1) \
  389. if(iter = iter->next, iter == NULL) { \
  390. goto LIST__FINISHED(iter); \
  391. } \
  392. else \
  393. LIST__MAINLOOP(iter) :
  394. // { user block; not in macro }
  395. // lockless queue
  396. #define LLQUEUE_DECL(type, prop) \
  397. typedef struct type ## _LLQLink { \
  398. struct type ## _LLQLink *next; \
  399. type prop; \
  400. } type ## _LLQLink; \
  401. typedef struct type ## _LLQList { \
  402. struct type ## _LLQLink *head, *tail; \
  403. int length; \
  404. } type ## _LLQueue;
  405. #define LLQ_INIT(list) \
  406. (list)->head = NULL; \
  407. (list)->tail = NULL; \
  408. (list)->length = 0;
  409. /*
  410. #define LLQ_PUSH_HEAD(list, prop, x) \
  411. do {
  412. typeof((list)->head) __new_link = calloc(1, sizeof(*__new_link)); \
  413. typeof((list)->head) __p;
  414. do{
  415. __p = (list)->head;
  416. } while(atomic_compare_exchange_strong(&(list)->head, &__p, __new_link);
  417. __new_link->next = __p;
  418. (list)->tail = __new_link; \
  419. if((list)->head == NULL) (list)->head = __new_link; \
  420. __new_link->prop = (x); \
  421. (list)->length++; \
  422. } while(0);
  423. */
  424. // heap
  425. /*
  426. // declare a heap
  427. #define HEAP(t) \
  428. struct { \
  429. size_t len, alloc, height; \
  430. t* data; \
  431. }
  432. // initialisze a vector
  433. #define HEAP_INIT(x) \
  434. do { \
  435. (x)->data = NULL; \
  436. (x)->len = 0; \
  437. (x)->alloc = 0; \
  438. (x)->height = 0; \
  439. } while(0)
  440. // helpers
  441. #define HEAP_LEN(x) ((x)->len)
  442. #define HEAP_ALLOC(x) ((x)->alloc)
  443. #define HEAP_HEIGHT(x) ((x)->height)
  444. #define HEAP_DATA(x) ((x)->data)
  445. #define HEAP_ITEM(x, i) (HEAP_DATA(x)[(i)])
  446. #define HEAP_TAIL(x) (HEAP_DATA(x)[HEAP_LEN(x)-1])
  447. #define HEAP_HEAD(x) (HEAP_DATA(x)[0])
  448. #define HEAP_PEEK(x) HEAD_HEAD(x)
  449. // check if a size increase is needed to insert one more item
  450. #define HEAP_CHECK(x) \
  451. do { \
  452. if(HEAP_LEN(x) >= HEAP_ALLOC(x)) { \
  453. HEAP_GROW(x); \
  454. } \
  455. } while(0)
  456. */
  457. // operations
  458. /*
  459. static void heap_down_min_i32(void* data, size_t stride, size_t int_offset) {
  460. int i = 0;
  461. int i1, i2, len;
  462. START:
  463. i1 = i * 2 + 1;
  464. i2 = i1 + 1;
  465. #define int_at(n) (*((uint32_t*)(data + (n * stride + int_offset))))
  466. if(len < i1) return;
  467. uint32_t x = int_at(i);
  468. if(x > int_at(i1)) {
  469. // swap, recurse
  470. i = i1;
  471. goto START;
  472. }
  473. if(len < i2) return;
  474. if(x > int_at(i2)) {
  475. // swap, recurse
  476. i = i2;
  477. goto START;
  478. }
  479. }
  480. */
  481. /*
  482. // increase size and assign the new entry
  483. #define HEAP_INSERT(x, e) \
  484. do { \
  485. HEAP_CHECK(x); \
  486. HEAP_DATA(x)[HEAP_LEN(x)] = (e); \
  487. HEAP_LEN(x)++; \
  488. } while(0)
  489. #define HEAP_POP(x)
  490. do { \
  491. HEAP_CHECK(x); \
  492. HEAP_LEN(x)++; \
  493. } while(0)
  494. #define HEAP_FREE(x) \
  495. do { \
  496. if(HEAP_DATA(x)) free(HEAP_DATA(x)); \
  497. HEAP_DATA(x) = NULL; \
  498. HEAP_LEN(x) = 0; \
  499. HEAP_ALLOC(x) = 0; \
  500. HEAP_HEIGHT(x) = 0; \
  501. } while(0)
  502. */
  503. #endif // __DS_H__