list.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. /*
  2. *
  3. * Copyright (c) 2011, Jue Ruan <ruanjue@gmail.com>
  4. *
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef __LIST_RJ_H
  20. #define __LIST_RJ_H
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include "sort.h"
  26. #include "mem_share.h"
  27. /**
  28. * Heap macros
  29. */
  30. //ary, size and cap must be explict variable, not expression
  31. #define array_heap_push(ary, size, cap, e_type, id, cmp_expr)\
  32. do { \
  33. e_type _pp_, _p_; \
  34. _p_ = (e_type)(id); \
  35. size_t i, j; \
  36. i = (size); \
  37. e_type a, b; \
  38. if((size_t)((size) + 1) > (size_t)(cap)){ \
  39. if((size_t)((size) + 1) < 0xFFFFFFFFU){ \
  40. (cap) = roundup_power2((size) + 1); \
  41. } else { \
  42. (cap) = (((size) + 1 + 0xFFFFFFFLLU - 1LLU) / 0xFFFFFFFLLU) * 0xFFFFFFFLLU; \
  43. } \
  44. (ary) = realloc((ary), sizeof(e_type) * (cap)); \
  45. if((ary) == NULL){ \
  46. fprintf(stderr, " -- Out of memory, try to allocate %llu bytes in %s, -- %s:%d --\n", (unsigned long long)(sizeof(e_type) * (cap)), __FUNCTION__, __FILE__, __LINE__); \
  47. print_backtrace(stderr, 20); \
  48. exit(1); \
  49. } \
  50. } \
  51. (ary)[(size)++] = _p_; \
  52. while(i){ \
  53. j = (i - 1) >> 1; \
  54. a = (ary)[i]; b = (ary)[j]; \
  55. if((cmp_expr) >= 0) break; \
  56. _pp_ = (ary)[i]; (ary)[i] = (ary)[j]; (ary)[j] = _pp_; \
  57. i = j; \
  58. } \
  59. } while(0)
  60. #define array_heap_remove(ary, len, cap, e_type, _idx, cmp_expr)\
  61. do { \
  62. e_type _pp_; \
  63. size_t swap, idx; \
  64. idx = (size_t)(_idx); \
  65. (ary)[idx] = (ary)[--(len)]; \
  66. e_type a, b; \
  67. while((size_t)((idx << 1) + 1) < (size_t)(len)){ \
  68. swap = idx; \
  69. a = (ary)[swap]; b = (ary)[(idx << 1) + 1]; \
  70. if((cmp_expr) > 0) swap = (idx << 1) + 1; \
  71. if(((idx << 1) + 2) < (size_t)(len)){ \
  72. a = (ary)[swap]; b = (ary)[(idx << 1) + 2]; \
  73. if((cmp_expr) > 0) swap = (idx << 1) + 2; \
  74. } \
  75. if(swap == idx) break; \
  76. _pp_ = (ary)[idx]; (ary)[idx] = (ary)[swap]; (ary)[swap] = _pp_; \
  77. idx = swap; \
  78. } \
  79. } while(0)
  80. #define array_heap_replace(ary, len, cap, e_type, _idx, _val, cmp_expr)\
  81. do { \
  82. e_type _pp_; \
  83. size_t swap, idx; \
  84. idx = (size_t)(_idx); \
  85. (ary)[idx] = _val; \
  86. e_type a, b; \
  87. while((size_t)((idx << 1) + 1) < (size_t)(len)){ \
  88. swap = idx; \
  89. a = (ary)[swap]; b = (ary)[(idx << 1) + 1]; \
  90. if((cmp_expr) > 0) swap = (idx << 1) + 1; \
  91. if(((idx << 1) + 2) < (size_t)(len)){ \
  92. a = (ary)[swap]; b = (ary)[(idx << 1) + 2]; \
  93. if((cmp_expr) > 0) swap = (idx << 1) + 2; \
  94. } \
  95. if(swap == idx) break; \
  96. _pp_ = (ary)[idx]; (ary)[idx] = (ary)[swap]; (ary)[swap] = _pp_; \
  97. idx = swap; \
  98. } \
  99. } while(0)
  100. #define array_heap_pop(ary, len, cap, e_type, cmp_expr) \
  101. ({ \
  102. e_type _ret_; \
  103. if(len){ _ret_ = ary[0]; array_heap_remove(ary, len, cap, e_type, 0, cmp_expr); } \
  104. else memset(&_ret_, 0xFFU, sizeof(e_type)); \
  105. _ret_; \
  106. })
  107. /**
  108. * List
  109. */
  110. #define define_list_core(list_type, e_type, size_type, inc_size) \
  111. \
  112. typedef struct { e_type* buffer; union { size_type size; size_type length; }; size_type cap; size_type off; u4i mem_zero:1, n_head:31; } list_type; \
  113. \
  114. static inline size_t list_type##_obj_desc_cnt(void *list, int idx){ \
  115. if(idx == 0) return ((list_type*)list)->size * sizeof(e_type); \
  116. else return 0; \
  117. } \
  118. \
  119. static inline void list_type##_obj_desc_post_load(void *obj, size_t aux_data){ \
  120. list_type *list; \
  121. UNUSED(aux_data); \
  122. list = (list_type*)obj; \
  123. list->cap = list->size; \
  124. } \
  125. \
  126. static const obj_desc_t list_type##_obj_desc = {.tag = TOSTR(_list_##list_type), .size = sizeof(list_type), .n_child = 1, .mem_type = {1}, .addr = {offsetof(list_type, buffer)}, .desc = {(struct obj_desc_t*)&OBJ_DESC_DATA}, .cnt = list_type##_obj_desc_cnt, .post = list_type##_obj_desc_post_load}; \
  127. \
  128. static inline void adv_##list_type##_init(list_type *list, size_type init_size, int mem_zero, u4i n_head){ \
  129. if(init_size == 0) init_size = 2; \
  130. list->size = 0; \
  131. list->off = 0; \
  132. list->cap = init_size; \
  133. list->mem_zero = mem_zero; \
  134. list->n_head = n_head; \
  135. if(n_head){ \
  136. list->buffer = (e_type*)calloc(list->cap + n_head, sizeof(e_type)); \
  137. list->buffer += n_head; \
  138. } else { \
  139. list->buffer = (e_type*)calloc(list->cap, sizeof(e_type)); \
  140. } \
  141. } \
  142. \
  143. static inline list_type* adv_init_##list_type(size_type init_size, int mem_zero, u4i n_head){ \
  144. list_type *list = (list_type*)malloc(sizeof(list_type)); \
  145. adv_##list_type##_init(list, init_size, mem_zero, n_head); \
  146. return list; \
  147. } \
  148. \
  149. static inline list_type* init_##list_type(size_type init_size){ \
  150. return adv_init_##list_type(init_size, 0, 0); \
  151. } \
  152. \
  153. static inline void list_type##_init(list_type *list, size_type init_size){ \
  154. adv_##list_type##_init(list, init_size, 0, 0); \
  155. } \
  156. \
  157. static inline int head_sl_##list_type(list_type *list, size_type len){ \
  158. if(list->n_head < len) return 0; \
  159. list->buffer -= len; \
  160. list->n_head -= len; \
  161. list->cap += len; \
  162. if(list->size) list->size += len; \
  163. return 1; \
  164. } \
  165. \
  166. static inline int head_sr_##list_type(list_type *list, size_type len){ \
  167. if(list->cap < len) return 0; \
  168. list->buffer += len; \
  169. list->n_head += len; \
  170. list->cap -= len; \
  171. if(list->size > len) list->size -= len; \
  172. else list->size = 0; \
  173. return 1; \
  174. } \
  175. \
  176. static inline void renew_##list_type(list_type *list, size_type init_size){ \
  177. if(list->buffer) free(list->buffer - list->n_head); \
  178. adv_##list_type##_init(list, init_size, list->mem_zero, list->n_head); \
  179. } \
  180. \
  181. static inline size_type count_##list_type(list_type *list){ return list->size; } \
  182. \
  183. static inline void clear_##list_type(list_type *list){ list->size = 0; list->off = 0; } \
  184. \
  185. static inline void zeros_##list_type(list_type *list){ memset(list->buffer, 0, list->cap * sizeof(e_type)); } \
  186. \
  187. static inline void encap_##list_type(list_type *list, size_type n){ \
  188. list->cap = encap_list((void**)&list->buffer, sizeof(e_type), list->size, list->cap, n, list->mem_zero, list->n_head); \
  189. } \
  190. \
  191. static inline void recap_##list_type(list_type *list, size_type n){ \
  192. if((size_t)n == (size_t)list->cap) return; \
  193. list->cap = n; \
  194. if(list->size > n) list->size = n; \
  195. list->buffer = realloc(list->buffer - list->n_head, (list->cap + list->n_head) * sizeof(e_type)) + list->n_head; \
  196. } \
  197. \
  198. static inline void pack_##list_type(list_type *list){ \
  199. return recap_##list_type(list, list->size); \
  200. } \
  201. \
  202. static inline void encap_and_zeros_##list_type(list_type *list, size_type n){ \
  203. if(((size_t)list->size) + ((size_t)n) <= (size_t)list->cap){ \
  204. } else { \
  205. if((size_t)(list->size + n) != ((size_t)list->size) + ((size_t)n)){ \
  206. fprintf(stderr, " -- elements size exceed %s's data type %s in %s -- %s:%d --\n", #list_type, #size_type, __FUNCTION__, __FILE__, __LINE__); \
  207. print_backtrace(stderr, 20); \
  208. fflush(stderr); \
  209. exit(1); \
  210. } \
  211. while(list->size + n > list->cap){ \
  212. if(list->cap < inc_size){ \
  213. list->cap <<= 1; \
  214. } else { \
  215. list->cap += inc_size; \
  216. } \
  217. } \
  218. list->buffer = realloc(list->buffer, list->cap * sizeof(e_type)); \
  219. } \
  220. memset(list->buffer + list->size, 0, n * sizeof(e_type)); \
  221. } \
  222. \
  223. static inline void clear_and_encap_##list_type(list_type *list, size_type n){ \
  224. list->size = 0; \
  225. list->off = 0; \
  226. encap_##list_type(list, n); \
  227. } \
  228. \
  229. static inline void clear_and_inc_##list_type(list_type *list, size_type n){ \
  230. list->size = 0; \
  231. list->off = 0; \
  232. encap_##list_type(list, n); \
  233. list->size = n; \
  234. } \
  235. \
  236. static inline void trunc_##list_type(list_type *list, size_type size){ \
  237. if(size > count_##list_type(list)) size = count_##list_type(list); \
  238. list->size -= size; \
  239. } \
  240. \
  241. static inline void set_##list_type##_size(list_type *list, size_type size){ list->size = size; } \
  242. \
  243. static inline void inc_##list_type(list_type *list, size_type size){ \
  244. encap_##list_type(list, size); \
  245. list->size += size; \
  246. } \
  247. \
  248. static inline void lazy_push_##list_type(list_type *list, e_type e){ list->buffer[list->size ++] = e; } \
  249. \
  250. static inline void push_##list_type(list_type *list, e_type e){ \
  251. encap_##list_type(list, 1); \
  252. list->buffer[list->size++] = e; \
  253. } \
  254. \
  255. static inline e_type* ring_ref_##list_type(list_type *list, size_type idx){ \
  256. idx = (list->off + idx) % list->cap; \
  257. return list->buffer + idx; \
  258. } \
  259. \
  260. static inline void ring_push_##list_type(list_type *list, e_type e){ \
  261. size_type idx; \
  262. idx = (list->off + list->size) % list->cap; \
  263. list->buffer[idx] = e; \
  264. if(list->size < list->cap){ \
  265. list->size ++; \
  266. } \
  267. } \
  268. \
  269. static inline e_type* ring_peer_##list_type(list_type *list){ \
  270. if(list->size){ \
  271. return list->buffer + list->size - 1; \
  272. } else return NULL; \
  273. } \
  274. \
  275. static inline e_type* ring_pop_##list_type(list_type *list){ \
  276. size_type idx; \
  277. if(list->size){ \
  278. list->size --; \
  279. idx = (list->off + list->size) % list->cap; \
  280. return list->buffer + idx; \
  281. } else return NULL; \
  282. } \
  283. \
  284. static inline void ring_shift_##list_type(list_type *list, e_type e){ \
  285. list->off = (list->off + list->cap - 1) % list->cap; \
  286. list->buffer[list->off] = e; \
  287. if(list->size < list->cap){ \
  288. list->size ++; \
  289. } \
  290. } \
  291. \
  292. static inline e_type* ring_unshift_##list_type(list_type *list){ \
  293. size_type idx; \
  294. if(list->size){ \
  295. list->size --; \
  296. list->off = (list->off + 1) % list->cap; \
  297. idx = (list->off + list->size) % list->cap; \
  298. return list->buffer + idx; \
  299. } else return NULL; \
  300. } \
  301. \
  302. static inline int fpush_##list_type(list_type *list, FILE *inp){ \
  303. int ret; \
  304. encap_##list_type(list, 1); \
  305. ret = fread(list->buffer + list->size, sizeof(e_type), 1, inp); \
  306. if(ret == 1) list->size ++; \
  307. return ret; \
  308. } \
  309. \
  310. static inline e_type* peer_##list_type(list_type *list){ \
  311. if(count_##list_type(list)){ \
  312. return list->buffer + list->size - 1; \
  313. } else return NULL; \
  314. } \
  315. \
  316. static inline e_type* head_##list_type(list_type *list){ \
  317. if(list->size) return list->buffer; \
  318. else return NULL; \
  319. } \
  320. \
  321. static inline e_type* tail_##list_type(list_type *list){ \
  322. if(list->size) return list->buffer + list->size - 1; \
  323. else return NULL; \
  324. } \
  325. static inline int pop_##list_type(list_type *list, e_type*e){ \
  326. if(count_##list_type(list)){ \
  327. list->size --; \
  328. *e = list->buffer[list->size]; \
  329. return 1; \
  330. } else return 0; \
  331. } \
  332. \
  333. static inline int fpop_##list_type(list_type *list, FILE *oup){ \
  334. if(list->size){ \
  335. fwrite(list->buffer + list->size - 1, sizeof(e_type), 1, oup); \
  336. list->size --; \
  337. return 1; \
  338. } else { \
  339. return 0; \
  340. } \
  341. } \
  342. \
  343. static inline void insert_##list_type(list_type *list, size_type idx, e_type e){ \
  344. if(idx > list->size) return; \
  345. encap_##list_type(list, 1); \
  346. if(idx == list->size){ \
  347. list->buffer[list->size] = e; \
  348. } else { \
  349. memmove(list->buffer + idx + 1, list->buffer + idx, (list->size - idx) * sizeof(e_type)); \
  350. list->buffer[idx] = e; \
  351. } \
  352. list->size ++; \
  353. } \
  354. \
  355. static inline void insert_array_##list_type(list_type *list, size_type idx, e_type *es, size_type size){ \
  356. if(idx > list->size) return; \
  357. encap_##list_type(list, size); \
  358. if(idx == list->size){ \
  359. } else { \
  360. memmove(list->buffer + idx + size, list->buffer + idx, (list->size - idx) * sizeof(e_type)); \
  361. } \
  362. memcpy(list->buffer + idx, es, size * sizeof(e_type)); \
  363. list->size += size; \
  364. } \
  365. \
  366. static inline void remove_##list_type(list_type *list, size_type idx){ \
  367. if(idx >= list->size) return; \
  368. if(idx + 1 < list->size){ \
  369. memmove(list->buffer + idx, list->buffer + idx + 1, (list->size - idx - 1) * sizeof(e_type)); \
  370. } \
  371. list->size --; \
  372. } \
  373. \
  374. static inline void remove_array_##list_type(list_type *list, size_type off, size_type len){ \
  375. if(off >= list->size) return; \
  376. if(off + len < list->size){ \
  377. memmove(list->buffer + off, list->buffer + off + len, (list->size - off - len) * sizeof(e_type)); \
  378. list->size -= len; \
  379. } else { \
  380. list->size = off; \
  381. } \
  382. } \
  383. \
  384. static inline void set_##list_type(list_type *list, size_type idx, e_type e){ list->buffer[idx] = e; } \
  385. \
  386. static inline e_type get_##list_type(list_type *list, size_type idx){ return list->buffer[idx]; } \
  387. \
  388. static inline e_type* ref_##list_type(list_type *list, size_type idx){ return list->buffer + idx; } \
  389. \
  390. static inline size_type offset_##list_type(list_type *list, e_type *e){ return e - list->buffer; } \
  391. \
  392. static inline e_type* next_ref_##list_type(list_type *list){ encap_##list_type(list, 1); list->size ++; return list->buffer + list->size - 1; } \
  393. \
  394. static inline e_type* ref_next_##list_type(list_type *list){ list->size ++; return list->buffer + list->size - 1; } \
  395. \
  396. static inline e_type* as_array_##list_type(list_type *list){ return list->buffer; } \
  397. \
  398. static inline void reverse_##list_type(list_type *list){ \
  399. size_type i, j; \
  400. e_type t; \
  401. if(count_##list_type(list) == 0) return; \
  402. i = 0; \
  403. j = count_##list_type(list) - 1; \
  404. while(i < j){ \
  405. t = get_##list_type(list, i); \
  406. set_##list_type(list, i, get_##list_type(list, j)); \
  407. set_##list_type(list, j, t); \
  408. i ++; \
  409. j --; \
  410. } \
  411. } \
  412. \
  413. static inline void sub_reverse_##list_type(list_type *list, size_type beg, size_type end){ \
  414. size_type i, j; \
  415. e_type t; \
  416. if(end <= beg) return; \
  417. i = beg; \
  418. j = end - 1; \
  419. while(i < j){ \
  420. t = get_##list_type(list, i); \
  421. set_##list_type(list, i, get_##list_type(list, j)); \
  422. set_##list_type(list, j, t); \
  423. i ++; \
  424. j --; \
  425. } \
  426. } \
  427. \
  428. static inline void append_##list_type(list_type *list1, list_type *list2){ \
  429. encap_##list_type(list1, count_##list_type(list2)); \
  430. memcpy(list1->buffer + list1->size, list2->buffer, sizeof(e_type) * list2->size); \
  431. list1->size += list2->size; \
  432. } \
  433. \
  434. static inline void append_array_##list_type(list_type *list1, e_type *ary, size_type size){ \
  435. if(size == 0) return; \
  436. encap_##list_type(list1, size); \
  437. memcpy(list1->buffer + list1->size, ary, sizeof(e_type) * size); \
  438. list1->size += size; \
  439. } \
  440. \
  441. static inline size_type write_##list_type(list_type *list, FILE *out){ \
  442. return fwrite(list->buffer, sizeof(e_type), count_##list_type(list), out); \
  443. } \
  444. \
  445. static inline size_type dump_##list_type(list_type *list, FILE *out){ \
  446. fwrite(&list->size, sizeof(size_type), 1, out); \
  447. fwrite(list->buffer, sizeof(e_type), list->size, out); \
  448. return sizeof(size_type) + sizeof(e_type) * list->size; \
  449. } \
  450. \
  451. static inline size_t mem_size_##list_type(list_type *list){ \
  452. return ((sizeof(list_type) + 7) / 8) * 8 + (list->size * sizeof(e_type) + 7) / 8 * 8; \
  453. } \
  454. \
  455. static inline size_t mem_dump_##list_type(list_type *list, FILE *out, void *addr){ \
  456. list_type clone; \
  457. size_t size; \
  458. b1i i, v; \
  459. size = mem_size_##list_type(list); \
  460. clone.size = list->size; \
  461. clone.cap = list->size; \
  462. clone.buffer = addr + (sizeof(list_type) + 7) / 8 * 8; \
  463. fwrite(&clone, sizeof(list_type), 1, out); \
  464. v = 0; \
  465. for(i=(sizeof(list_type) + 7) / 8 * 8 - sizeof(list_type);i>0;i--) fwrite(&v, 1, 1, out); \
  466. fwrite(list->buffer, sizeof(e_type), list->size, out); \
  467. for(i=(sizeof(e_type) * list->size + 7) / 8 * 8 - sizeof(e_type) * list->size;i>0;i--) fwrite(&v, 1, 1, out); \
  468. return size; \
  469. } \
  470. \
  471. static inline list_type* load_##list_type(FILE *inp){ \
  472. list_type *list; \
  473. size_type n; \
  474. list = (list_type*)malloc(sizeof(list_type)); \
  475. if((n = fread(&list->size, sizeof(size_type), 1, inp)) != 1){ \
  476. free(list); return NULL; \
  477. } \
  478. list->cap = list->size; \
  479. list->buffer = (e_type*)malloc(sizeof(e_type) * list->cap); \
  480. if(list->buffer == NULL){ \
  481. fprintf(stderr, " Out of memory in load_%s \n", #list_type); fflush(stderr); exit(1); \
  482. print_backtrace(stderr, 20); \
  483. } \
  484. if((n = fread(list->buffer, sizeof(e_type), list->size, inp)) != list->size){ \
  485. print_backtrace(stderr, 20); \
  486. free(list->buffer); free(list); return NULL; \
  487. } \
  488. return list; \
  489. } \
  490. \
  491. static inline void free_##list_type(list_type *list){ if(list){ free(list->buffer - list->n_head); free(list); } } \
  492. \
  493. static inline void list_type##_free(list_type *list){ free(list->buffer); list->buffer = NULL; } \
  494. #define define_list_ext(list_type, e_type, size_type, cmp_func) \
  495. static inline size_type delete_##list_type(list_type *list, e_type e){ \
  496. size_type i, ret; \
  497. ret = 0; \
  498. for(i=list->size;i>0;i--){ \
  499. if(cmp_func(list->buffer[i-1], e, NULL) == 0){ \
  500. if(i < list->size){ \
  501. memmove(list->buffer + i - 1, list->buffer + i, (list->size - i) * sizeof(e_type)); \
  502. } \
  503. list->size --; \
  504. ret ++; \
  505. } \
  506. } \
  507. return ret; \
  508. } \
  509. \
  510. static inline size_type occ_##list_type(list_type *list, e_type e){ \
  511. size_type i, n; \
  512. for(i=0,n=0;i<list->size;i++){ \
  513. if(cmp_func(list->buffer[i], e, NULL) == 0) n++; \
  514. } \
  515. return n; \
  516. } \
  517. \
  518. static inline size_type replace_##list_type(list_type *list, e_type from, e_type to){ \
  519. size_type i, ret; \
  520. ret = 0; \
  521. for(i=0;i<list->size;i++){ \
  522. if(cmp_func(list->buffer[i], from, NULL) == 0){ \
  523. list->buffer[i] = to; \
  524. ret ++; \
  525. } \
  526. } \
  527. return ret; \
  528. } \
  529. \
  530. static inline size_type locate_##list_type(list_type *list, e_type e, size_type start){ \
  531. size_type i; \
  532. for(i=start;i<list->size;i++){ \
  533. if(cmp_func(list->buffer[i], e, NULL) == 0) return i; \
  534. } \
  535. return i; \
  536. } \
  537. \
  538. define_quick_sort(sort_##list_type##_core, e_type, cmp_func); \
  539. \
  540. static inline void sort_##list_type(list_type *list){ sort_##list_type##_core(ref_##list_type(list, 0), count_##list_type(list), NULL); }
  541. #define define_list(name, e_type) define_list_core(name, e_type, size_t, 0xFFFFFU)
  542. #define native_number_cmp(e1, e2, obj) (((e1) == (e2))? 0 : (((e1) < (e2))? -1 : 1))
  543. #define define_native_list(name, e_type) \
  544. define_list_core(name, e_type, size_t, 0xFFFFFU); \
  545. define_list_ext(name, e_type, size_t, native_number_cmp);
  546. define_native_list(u8list, u1i);
  547. define_native_list(u1v, u1i);
  548. define_native_list(u16list, u2i);
  549. define_native_list(u2v, u2i);
  550. define_native_list(u32list, u4i);
  551. define_native_list(u4v, u4i);
  552. define_native_list(u64list, u8i);
  553. define_native_list(u8v, u8i);
  554. define_native_list(b8list, b1i);
  555. define_native_list(b1v, b1i);
  556. define_native_list(b16list, b2i);
  557. define_native_list(b2v, b2i);
  558. define_native_list(b32list, b4i);
  559. define_native_list(b4v, b4i);
  560. define_native_list(b64list, b8i);
  561. define_native_list(b8v, b8i);
  562. define_native_list(f4v, f4i);
  563. define_native_list(f8v, f8i);
  564. define_list(vplist, void*);
  565. define_list(cplist, char*);
  566. // mem_share for deep dump of cplist
  567. static inline size_t cplist_deep_obj_desc_cnt(void *list, int idx){
  568. if(idx == 0) return ((cplist*)list)->size;
  569. else return 1;
  570. }
  571. static const obj_desc_t cplist_deep_obj_desc = {.tag = "cplist_deep_dump", .size = sizeof(cplist), .n_child = 1, .mem_type = {3}, .addr = {offsetof(cplist, buffer)}, .desc = {(struct obj_desc_t*)&OBJ_DESC_CHAR_ARRAY}, .cnt = cplist_deep_obj_desc_cnt, .post=NULL};
  572. #define define_recycle_list_array(name, list_type) \
  573. typedef struct { \
  574. vplist *array; \
  575. vplist *dustbin; \
  576. } name; \
  577. \
  578. static inline name* init_##name(){ \
  579. name *g; \
  580. g = (name*)malloc(sizeof(name)); \
  581. g->buffer = init_vplist(4); \
  582. g->dustbin = init_vplist(4); \
  583. return g; \
  584. } \
  585. \
  586. static inline void free_##name(name *g){ \
  587. list_type *v; \
  588. size_t i; \
  589. for(i=0;i<g->array->size;i++){ \
  590. v = (list_type*)get_vplist(g->array, i); \
  591. if(v) free_##list_type(v); \
  592. } \
  593. for(i=0;i<g->dustbin->size;i++){ \
  594. v = (list_type*)get_vplist(g->dustbin, i); \
  595. if(v) free_##list_type(v); \
  596. } \
  597. free_vplist(g->array); \
  598. free_vplist(g->dustbin); \
  599. free(g); \
  600. } \
  601. \
  602. static inline list_type* fetch_##name(name *g){ \
  603. list_type *v; \
  604. if(g->dustbin->size) v = (list_type*)g->dustbin->buffer[--g->dustbin->size]; \
  605. else v = init_##list_type(4); \
  606. return v; \
  607. } \
  608. \
  609. static inline void recyc_##name(name *g, list_type *v){ \
  610. push_vplist(g->dustbin, v); \
  611. } \
  612. \
  613. static inline void recyc_all_##name(name *g, vplist *vs){ \
  614. append_vplist(g->dustbin, vs); \
  615. vs->size = 0; \
  616. }
  617. // e.g. define_recycle_list(u8r, u8i, u8i, *a = 0, NULL)
  618. // u8r, when increase an element, set the to 0 (*a = 0), when free it, do nothing (NULL)
  619. #define define_recycle_list(list_type, e_type, size_type, e_init, e_free) \
  620. typedef struct { \
  621. e_type *buffer; \
  622. size_type size, cap; \
  623. size_type *recyc; \
  624. size_type rsize, rcap; \
  625. u8i userdata; \
  626. } list_type; \
  627. \
  628. static inline list_type* init_##list_type(size_type size){ \
  629. list_type *list; \
  630. if(size < 2) size = 2; \
  631. list = malloc(sizeof(list_type)); \
  632. list->size = 0; \
  633. list->cap = size; \
  634. list->buffer = calloc(size, sizeof(e_type)); \
  635. list->recyc = calloc(2, sizeof(size_type)); \
  636. list->rsize = 0; \
  637. list->rcap = 2; \
  638. list->userdata = 0; \
  639. return list; \
  640. } \
  641. \
  642. static inline void free_##list_type(list_type *list){ \
  643. e_type* a; \
  644. size_type i; \
  645. for(i=0;i<list->size;i++){ \
  646. a = list->buffer + i; \
  647. UNUSED(e_free); \
  648. } \
  649. UNUSED(a); \
  650. free(list->buffer); \
  651. free(list->recyc); \
  652. free(list); \
  653. } \
  654. \
  655. static inline void encap_##list_type(list_type *list, size_type inc){ \
  656. if(list->rsize >= inc) return; \
  657. inc -= list->rsize; \
  658. list->cap = encap_list((void**)&list->buffer, sizeof(e_type), list->size, list->cap, inc, 0, 0); \
  659. } \
  660. \
  661. static inline size_type fetch_##list_type(list_type *list){ \
  662. e_type* a; \
  663. if(list->rsize){ \
  664. return list->recyc[--list->rsize]; \
  665. } \
  666. list->cap = encap_list((void**)&list->buffer, sizeof(e_type), list->size, list->cap, 1, 0, 0); \
  667. a = list->buffer + list->size; \
  668. UNUSED(e_init); \
  669. UNUSED(a); \
  670. return list->size ++; \
  671. } \
  672. \
  673. static inline e_type* ref_##list_type(list_type *list, size_type idx){ \
  674. return list->buffer + idx; \
  675. } \
  676. \
  677. static inline size_type offset_##list_type(list_type *list, e_type *e){ \
  678. return e - list->buffer; \
  679. } \
  680. \
  681. static inline void recyc_##list_type(list_type *list, size_type idx){ \
  682. list->rcap = encap_list((void**)&list->recyc, sizeof(size_type), list->rsize, list->rcap, 1, 0, 0); \
  683. list->recyc[list->rsize++] = idx; \
  684. } \
  685. \
  686. static inline e_type* pop_##list_type(list_type *list){ \
  687. size_type idx; \
  688. idx = fetch_##list_type(list); \
  689. return ref_##list_type(list, idx); \
  690. } \
  691. \
  692. static inline void push_##list_type(list_type *list, e_type* e){ \
  693. recyc_##list_type(list, offset_##list_type(list, e)); \
  694. } \
  695. \
  696. static inline void recyc_all_##list_type(list_type *list){ \
  697. size_type i; \
  698. list->rsize = 0; \
  699. list->rcap = encap_list((void**)&list->recyc, sizeof(size_type), list->rsize, list->rcap, list->size, 0, 0); \
  700. for(i=0;i<list->size;i++){ \
  701. list->recyc[i] = i; \
  702. } \
  703. list->rsize = list->size; \
  704. }
  705. # endif