#ifndef PACKAGE__PROG__PRJLIBS__VEC_H #define PACKAGE__PROG__PRJLIBS__VEC_H #include "standards.h" #include #include #include "types.h" #include "warn.h" typedef struct { unsigned char* s; /* pointer to allocated bytes */ size_t len; /* count of bytes exposed to the caller */ size_t a; /* count of allocated bytes */ } vec_type; /* These might belong somewhere else... */ enum { vec_size_bits=sizeof (size_t)*CHAR_BIT }; #define VEC_ALIGN(type) offsetof(struct { char c; type t; }, t) #define VEC_SIZE_UP(sz0, sz1) \ (WARN_TYPE(size_t, sz0), \ WARN_TYPE(size_t, sz1), \ (((size_t)(sz0)+((size_t)(sz1)-1u))/(size_t)(sz1)*(size_t)(sz1))) #define VEC_T(type) union { vec_type generic_vector; type* typecheck; } #define VEC_TD(type, name) typedef VEC_T(type) name #define VEC_0(type) { { (unsigned char*)NULL, 0, 0 } } #define VEC_GV(type, vec) \ (WARN_TYPE(vec_type, (vec)->generic_vector), \ WARN_TYPE(type*, (vec)->typecheck), \ &(vec)->generic_vector) #define VEC_GV_S( type, vec) (VEC_GV(type, vec)->s) #define VEC_GV_LEN(type, vec) (VEC_GV(type, vec)->len) #define VEC_GV_A( type, vec) (VEC_GV(type, vec)->a) typedef void vec_ftype(void*); extern vec_ftype vec_init; #define VEC_INIT(type, vec) vec_init(VEC_GV(type, vec)) extern vec_ftype vec_free; #define VEC_FREE(type, vec) vec_free(VEC_GV(type, vec)) #define VEC_CAP(type, vec) (VEC_GV_A(type, vec)/sizeof (type)) #define VEC_LEN(type, vec) (VEC_GV_LEN(type, vec)/sizeof (type)) #define VEC_TRUNC(type, vec, n) \ (WARN_TYPE(size_t, n), \ VEC_LEN(type, vec)<=(n) \ ? (errno=EINVAL, -1) \ : (VEC_GV_LEN(type, vec)=(size_t)(n)*sizeof (type), 0)) extern type_status vec_alloc(size_t, vec_type*, size_t, type_bool); #define VEC_ALLOC(type, vec, n, plus) \ vec_alloc(sizeof (type), VEC_GV(type, vec), (n), (plus)) #define VEC_ELTS(type, vec) ((type*)VEC_GV_S(type, vec)) extern size_t vec_diffi(size_t, vec_type const*, vec_type const*); #define VEC_DIFFI(type, vec0, vec1) \ vec_diffi(sizeof (type), VEC_GV(type, vec0), VEC_GV(type, vec1)) #define VEC_EQ(type, vec0, vec1) \ (VEC_GV_LEN(type, vec0)==VEC_GV_LEN(type, vec1) && \ VEC_GV_LEN(type, vec0)==VEC_DIFFI(type, vec0, vec1)) extern type_status vec_ins(size_t, vec_type*, size_t, void const*, size_t); #define VEC_INS(type, vec, i, d, n) \ (WARN_TYPE(type const*, d), \ vec_ins(sizeof (type), VEC_GV(type, vec), (i), (d), (n))) #define VEC_INSA(type, vec, i, arr, trim) \ (WARN_TYPE(type_bool, trim), \ /* XXX: check that arr is a (const or non-const) array, not a pointer */ \ VEC_INS(type, vec, i, arr, sizeof (arr)/sizeof (type)-((trim)!=0))) #define VEC_PUSHN(type, vec, d, n) VEC_INS(type, vec, VEC_LEN(type, vec), d, n) #define VEC_PUSHA(type, vec, arr, trim) \ VEC_INSA(type, vec, VEC_LEN(type, vec), arr, trim) #define VEC_PUSH(type, vec, value) \ (VEC_PUSHN(type, vec, (type*)NULL, 1)==0 \ ? ((void)(VEC_ELTS(type, vec)[VEC_LEN(type, vec)-1]=(value)), 0) \ : -1) #define VEC_UNSHIFTN(type, vec, d, n) VEC_INS(type, vec, 0, d, n) #define VEC_UNSHIFTA(type, vec, arr, trim) VEC_INSA(type, vec, 0, arr, trim) #define VEC_UNSHIFT(type, vec, value) \ (VEC_UNSHIFTN(type, vec, (type*)NULL, 1)==0 \ ? ((void)(VEC_ELTS(type, vec)[0]=(value)), 0) \ : -1) extern type_status vec_cut(size_t, vec_type*, size_t, void*, size_t); #define VEC_CUT(type, vec, i, d, n) \ (WARN_TYPE(type*, d), \ vec_cut(sizeof (type), VEC_GV(type, vec), (i), (d), (n))) #define VEC_POPN(type, vec, n) \ (WARN_TYPE(size_t, n), \ VEC_LEN(type, vec)<(size_t)(n) /* XXX */ \ ? (errno=EINVAL, (type*)NULL) \ : (VEC_GV_LEN(type, vec)-=(size_t)(n)*sizeof (type), \ (type*)(VEC_GV_S(type, vec)+VEC_GV_LEN(type, vec)))) #define VEC_POP(type, vec) VEC_POPN(type, vec, 1) /* XXX */ #define VEC_SHIFTN(type, vec, n) VEC_CUT(type, vec, 0, NULL, n) extern unsigned char* vec_shift(size_t, vec_type*); #define VEC_SHIFT(type, vec) \ ((type*)vec_shift(sizeof (type), VEC_GV(type, vec))) extern size_t vec_bsrch(size_t, vec_type const*, void const*, int (*)(void const*, void const*), type_bool); #define VEC_BSRCHF(type, vec, d, compar) \ (WARN_TYPE(type*, d), \ vec_bsrch(sizeof (type), VEC_GV(type, vec), (d), (compar), 1)) #define VEC_BSRCHL(type, vec, d, compar) \ (WARN_TYPE(type*, d), \ vec_bsrch(sizeof (type), VEC_GV(type, vec), (d), (compar), 0)) #define VEC_BSRCHC(type, vec, d, compar) \ (VEC_BSRCHL(type, vec, d, compar)-VEC_BSRCHF(type, vec, d, compar)) #endif