/* Public domain. */ #ifndef GEN_BUNCH_H #define GEN_BUNCH_H #include "gen_alloc.h" #include "bitarray.h" /* user */ #define GEN_BUNCH_ZERO { GEN_ALLOC_ZERO, BITARRAY_ZERO, 0 } #define gen_bunch_p(sb, i) ((i) ? ((sb)->x.s+((i)-1)) : 0) /* .h */ #define GEN_BUNCH_typedef(tbunch, talloc) \ typedef struct tbunch { talloc x ; bitarray used ; unsigned int n ; } tbunch, *tbunch##_ref ; #define GEN_BUNCH_FPROTOTYPES(tbunch, talloc, type) \ extern void tbunch##_free (tbunch *) ; \ extern int tbunch##_ready (tbunch *, unsigned int) ; \ extern int tbunch##_readyplus (tbunch *, unsigned int) ; \ extern int tbunch##_delete (tbunch *, unsigned int) ; \ extern unsigned int tbunch##_new (tbunch *) ; \ #define GEN_BUNCH_PROTOTYPES(tbunch, talloc, type) \ GEN_BUNCH_typedef(tbunch, talloc) \ GEN_BUNCH_FPROTOTYPES(tbunch, talloc, type) \ /* .c */ #define GEN_BUNCH_free(tbunch, talloc) \ void tbunch##_free (tbunch *sb) \ { \ bitarray_free(&sb->used) ; \ talloc##_free(&sb->x) ; \ sb->n = 0 ; \ } \ #define GEN_BUNCH_ready(tbunch, talloc) \ int tbunch##_ready (tbunch *sb, unsigned int n) \ { \ unsigned char wasnull = !sb->x.s ; \ if (!talloc##_ready(&sb->x, n)) return 0 ; \ if (!bitarray_ready(&sb->used, n)) \ { \ if (wasnull) talloc##_free(&sb->x) ; \ return 0 ; \ } \ return 1 ; \ } \ #define GEN_BUNCH_readyplus(tbunch, talloc) \ int tbunch##_readyplus (tbunch *sb, unsigned int n) \ { \ return tbunch##_ready(sb, n + sb->n) ; \ } \ #define GEN_BUNCH_delete(tbunch) \ int tbunch##_delete (tbunch *sb, unsigned int i) \ { \ if (!i-- || !bitarray_testandclear(&sb->used, i)) return 0 ; \ sb->n-- ; \ if (i+1 == sb->x.len) \ while (sb->x.len && !bitarray_isset(&sb->used, sb->x.len - 1)) \ sb->x.len-- ; \ return 1 ; \ } \ #define GEN_BUNCH_new(tbunch, talloc, type, base, minfree) \ unsigned int tbunch##_new (tbunch *sb) \ { \ register unsigned int i = sb->x.len ; \ if (i < sb->x.a) \ { \ if (!bitarray_ready(&sb->used, i)) return 0 ; \ sb->x.len++ ; \ } \ else if ((sb->n + (minfree) + (i >> 5)) < i) \ i = bitarray_firstclear(&sb->used) ; \ if (i >= sb->x.len) \ { \ unsigned char wasnull = !sb->x.s ; \ if (!talloc##_readyplus(&sb->x, (base))) return 0 ; \ if (!bitarray_ready(&sb->used, sb->x.a)) \ { \ if (wasnull) talloc##_free(&sb->x) ; \ return 0 ; \ } \ i = sb->x.len++ ; \ } \ bitarray_set(&sb->used, i) ; \ sb->n++ ; \ return i+1 ; \ } \ #define GEN_BUNCH_DEFS(tbunch, talloc, type, base, minfree) \ GEN_BUNCH_free(tbunch, talloc) \ GEN_BUNCH_ready(tbunch, talloc) \ GEN_BUNCH_readyplus(tbunch, talloc) \ GEN_BUNCH_delete(tbunch) \ GEN_BUNCH_new(tbunch, talloc, type, base, minfree) \ #define GEN_BUNCH_STATIC_DEFS(tbunch, talloc, type, base, minfree) \ static GEN_BUNCH_free(tbunch, talloc) \ static GEN_BUNCH_ready(tbunch, talloc) \ static GEN_BUNCH_readyplus(tbunch, talloc) \ static GEN_BUNCH_delete(tbunch) \ static GEN_BUNCH_new(tbunch, talloc, type, base, minfree) \ #endif