#ifndef MIAO_H_INCLUDED #define MIAO_H_INCLUDED /* MIAO Minimalistic Array Operations, inspired by kvec->h-> */ #include #ifndef miao_realloc #define miao_realloc(PTR, SIZE) realloc((PTR), (SIZE)) #endif #define miao_of_type(TYPE) { TYPE * a; TYPE * aux; size_t n; size_t m; } #define miao_t(TYPE) struct miao_of_type(TYPE) #define miao_struct(NAME, TYPE) struct NAME miao_of_type(TYPE) #define miao_init(ARR) ((ARR)->n = (ARR)->m = 0, (ARR)->a = NULL, (ARR)) #define miao_done(ARR) do { free((ARR)->a); miao_init((ARR)); } while (0) #define miao_unsafe_get_ptr(ARR, I) (((ARR)->a)+(I)) #define miao_unsafe_get(ARR, I) (((ARR)->a)[(I)]) #define miao_elsize(ARR) (sizeof *((ARR)->a)) #define miao_cap(ARR) ((ARR)->m) #define miao_size(ARR) ((ARR)->n) #define miao_size_for(ARR, AMOUNT) (miao_elsize(ARR) * (AMOUNT)) #define miao_total_size(ARR) miao_size_for(ARR, miao_size(ARR)) #define miao_out_of_bounds(ARR, I) ((size_t)(I) >= (ARR)->m) #define miao_get_ptr(ARR, I) (miao_out_of_bounds(ARR, I) ? NULL: miao_unsafe_get_ptr(ARR, I)) #define miao_get(ARR, I, DEFAULT) (miao_out_of_bounds(ARR, I) ? DEFAULT : miao_unsafe_get(ARR, I)) #define miao_resize(ARR, CAP) \ ( \ (ARR)->m = (CAP), \ (ARR)->aux = miao_realloc((ARR)->a, miao_size_for(ARR, (ARR)->m)), \ (ARR)->aux ? ((ARR)->a = ARR->aux) : NULL \ ) #define miao_grow(ARR, SIZE) \ (SIZE >= miao_cap(ARR) ? miao_resize(ARR, SIZE) : (ARR)->a ) #define miao_unsafe_pop_ptr(ARR) ((ARR)->n--, ((ARR)->a + (ARR)->n)) #define miao_unsafe_pop(ARR) ((ARR)->n--, (ARR)->a[(ARR)->n]) #define miao_pop(ARR, DEFAULT) (((ARR)->n > 0) ? miao_unsafe_pop(ARR) : DEFAULT) #define miao_pop_ptr(ARR) (((ARR)->n > 0) ? miao_unsafe_pop_ptr(ARR) : NULL) #define miao_unsafe_push(ARR, VAL) ((ARR)->n++, (ARR)->a[(ARR)->n] = (VAL)) #define miao_push(ARR, VAL) \ (miao_grow(ARR, ((ARR)->n + 1)) ? miao_unsafe_push(ARR, VAL) : NULL) #define miao_push_ptr(ARR) \ ( \ (miao_grow(ARR, ((ARR)->n + 1))) ? \ ((ARR)->n++, miao_get_ptr(ARR, (ARR)->n - 1)) \ : NULL \ ) #define miao_copy(DEST, SRC) \ ( \ miao_grow(DEST, miao_size(SRC)) ? \ ( (DEST)->n = miao_size(SRC), \ memcpy((DEST)->a, (SRC)->a, miao_total_size(DEST)) \ , DEST \ ) : NULL \ ) #define miao_qsort(ARR, COMPARE) \ ( \ (ARR)->a ? \ ( qsort((ARR)->a, miao_size(ARR), miao_elsize(ARR), COMPARE) \ , (ARR)->a ) \ : NULL \ ) #define miao_bsearch(ARR, COMPARE, KEY) \ (bsearch(KEY, (ARR)->a, miao_size(ARR), miao_elsize(ARR), COMPARE)) #define miao_each_ptr(ARR, ACTION, DATA) \ { size_t miao_i__ ; \ for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \ if(ACTION(miao_i__, miao_unsafe_get_ptr(ARR, miao_i__), DATA)) break; \ } \ } while(0); #define miao_each(ARR, ACTION, DATA) \ { size_t miao_i__ ; \ for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \ if(ACTION(miao_i__, miao_unsafe_get(ARR, miao_i__), DATA)) break; \ } \ } while(0); #define miao_each_with_result(ARR, ACTION, RESULT, CHECK, DATA) \ { size_t miao_i__ ; \ for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \ (RESULT) = ACTION(miao_i__, miao_unsafe_get(ARR, miao_i__), DATA); \ if (CHECK(RESULT, DATA)) break; \ } \ } while(0); #define miao_each_ptr_with_result(ARR, ACTION, RESULT, CHECK, DATA) \ { size_t miao_i__ ; \ for (miao_i__ = 0; miao_i__ < miao_size(ARR) ; miao_i__ ++) { \ (RESULT) = ACTION(miao_i__, miao_unsafe_get_ptr(ARR, miao_i__), DATA); \ if (CHECK(RESULT, DATA)) break; \ } \ } while(0); #endif