miao.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #ifndef MIAO_H_INCLUDED
  2. #define MIAO_H_INCLUDED
  3. /* MIAO Minimalistic Array Operations, inspired by kvec->h-> */
  4. #include <stdlib.h>
  5. #ifndef miao_realloc
  6. #define miao_realloc(PTR, SIZE) realloc((PTR), (SIZE))
  7. #endif
  8. #define miao_of_type(TYPE) { TYPE * a; TYPE * aux; size_t n; size_t m; }
  9. #define miao_t(TYPE) struct miao_of_type(TYPE)
  10. #define miao_struct(NAME, TYPE) struct NAME miao_of_type(TYPE)
  11. #define miao_init(ARR) ((ARR)->n = (ARR)->m = 0, (ARR)->a = NULL, (ARR))
  12. #define miao_done(ARR) do { free((ARR)->a); miao_init((ARR)); } while (0)
  13. #define miao_unsafe_get_ptr(ARR, I) (((ARR)->a)+(I))
  14. #define miao_unsafe_get(ARR, I) (((ARR)->a)[(I)])
  15. #define miao_elsize(ARR) (sizeof *((ARR)->a))
  16. #define miao_cap(ARR) ((ARR)->m)
  17. #define miao_size(ARR) ((ARR)->n)
  18. #define miao_size_for(ARR, AMOUNT) (miao_elsize(ARR) * (AMOUNT))
  19. #define miao_total_size(ARR) miao_size_for(ARR, miao_size(ARR))
  20. #define miao_out_of_bounds(ARR, I) ((size_t)(I) >= (ARR)->m)
  21. #define miao_get_ptr(ARR, I) (miao_out_of_bounds(ARR, I) ? NULL: miao_unsafe_get_ptr(ARR, I))
  22. #define miao_get(ARR, I, DEFAULT) (miao_out_of_bounds(ARR, I) ? DEFAULT : miao_unsafe_get(ARR, I))
  23. #define miao_resize(ARR, CAP) \
  24. ( \
  25. (ARR)->m = (CAP), \
  26. (ARR)->aux = miao_realloc((ARR)->a, miao_size_for(ARR, (ARR)->m)), \
  27. (ARR)->aux ? ((ARR)->a = ARR->aux) : NULL \
  28. )
  29. #define miao_grow(ARR, SIZE) \
  30. (SIZE >= miao_cap(ARR) ? miao_resize(ARR, SIZE) : (ARR)->a )
  31. #define miao_unsafe_pop_ptr(ARR) ((ARR)->n--, ((ARR)->a + (ARR)->n))
  32. #define miao_unsafe_pop(ARR) ((ARR)->n--, (ARR)->a[(ARR)->n])
  33. #define miao_pop(ARR, DEFAULT) (((ARR)->n > 0) ? miao_unsafe_pop(ARR) : DEFAULT)
  34. #define miao_pop_ptr(ARR) (((ARR)->n > 0) ? miao_unsafe_pop_ptr(ARR) : NULL)
  35. #define miao_unsafe_push(ARR, VAL) \
  36. ((ARR)->a[(ARR)->n] = (VAL), (ARR)->n++, ((ARR)->a + (ARR)->n))
  37. #define miao_push(ARR, VAL) \
  38. ( \
  39. (miao_grow(ARR, ((ARR)->n + 1))) ? \
  40. miao_unsafe_push(ARR, VAL) : NULL \
  41. )
  42. #define miao_push_ptr(ARR) \
  43. ( \
  44. (miao_grow(ARR, ((ARR)->n + 1))) ? \
  45. ((ARR)->n++, miao_get_ptr(ARR, (ARR)->n - 1)) \
  46. : NULL \
  47. )
  48. #define miao_copy(DEST, SRC) \
  49. ( \
  50. miao_grow(DEST, miao_size(SRC)) ? \
  51. ( (DEST)->n = miao_size(SRC), \
  52. memcpy((DEST)->a, (SRC)->a, miao_total_size(DEST)) \
  53. , DEST \
  54. ) : NULL \
  55. )
  56. #define miao_qsort(ARR, COMPARE) \
  57. ( \
  58. (ARR)->a ? \
  59. ( qsort((ARR)->a, miao_size(ARR), miao_elsize(ARR), COMPARE) \
  60. , (ARR)->a ) \
  61. : NULL \
  62. )
  63. #define miao_bsearch(ARR, COMPARE, KEY) \
  64. (bsearch(KEY, (ARR)->a, miao_size(ARR), miao_elsize(ARR), COMPARE))
  65. #define miao_each_ptr(ARR, ACTION, DATA) \
  66. { size_t miao_i__ ; \
  67. for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \
  68. if(ACTION(miao_i__, miao_unsafe_get_ptr(ARR, miao_i__), DATA)) break; \
  69. } \
  70. } while(0);
  71. #define miao_each(ARR, ACTION, DATA) \
  72. { size_t miao_i__ ; \
  73. for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \
  74. if(ACTION(miao_i__, miao_unsafe_get(ARR, miao_i__), DATA)) break; \
  75. } \
  76. } while(0);
  77. #define miao_each_with_result(ARR, ACTION, RESULT, CHECK, DATA) \
  78. { size_t miao_i__ ; \
  79. for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \
  80. (RESULT) = ACTION(miao_i__, miao_unsafe_get(ARR, miao_i__), DATA); \
  81. if (CHECK(RESULT, DATA)) break; \
  82. } \
  83. } while(0);
  84. #define miao_each_ptr_with_result(ARR, ACTION, RESULT, CHECK, DATA) \
  85. { size_t miao_i__ ; \
  86. for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \
  87. (RESULT) = ACTION(miao_i__, miao_unsafe_get_ptr(ARR, miao_i__), DATA); \
  88. if (CHECK(RESULT, DATA)) break; \
  89. } \
  90. } while(0);
  91. #define miao_delete(ARR, INDEX) \
  92. ( miao_out_of_bounds(ARR, ((size_t)INDEX)) ? 0 : \
  93. /* Copy over everything from index + 1 */ \
  94. (memmove(ARR->a + INDEX, ARR->a + INDEX + 1, \
  95. (ARR->n - INDEX - 1) * sizeof(ARR->n) ) , \
  96. (1 + ARR->n--)) \
  97. )
  98. #define miao_index_of(ARR, ENTRY) ( (ENTRY) - ((ARR)->a) )
  99. #define miao_delete_entry(ARR, ENTRY) \
  100. ( miao_delete(ARR, miao_index_of(ARR, ENTRY)) )
  101. #define miao_delete_bsearch(ARR, COMPARE, ENTRY) \
  102. ( ARR->aux = miao_bsearch(ARR, COMPARE, ENTRY) , \
  103. ARR->aux ? miao_delete_entry(ARR, ARR->aux) : 0 )
  104. #endif