%% options copyright owner = Dirk Krause copyright year = 2011-2013 license = bsd %% header #include "dk3conf.h" #include "dk3types.h" #ifdef __cplusplus extern "C" { #endif /** Open a bit field (bit array). @param nbits Number of bits. @param app Application structure for diagnostics, may be NULL. @return Pointer to new bit field on success, NULL on error. */ dk3_bf_t * dk3bf_open_app(size_t nbits, dk3_app_t *app); /** Close bit field. @param b Bit field to close. */ void dk3bf_close(dk3_bf_t *b); /** Set or reset one bit. @param b Bit field. @param n Index of bit to set. @param v New bit value (1 or 0). */ void dk3bf_set(dk3_bf_t *b, size_t n, int v); /** Get one bit value. @param b Bit field. @param n Index of bit. @return 1 or 0 depending on the bit value. */ int dk3bf_get(dk3_bf_t *b, size_t n); /** Open a bit matrix. @param x Number of columns. @param y Number of rows. @param app Application structure for diagnostics, may be NULL. @return Pointer to new bit matrix on success, NULL on error. */ dk3_bm_t * dk3bm_open(size_t x, size_t y, dk3_app_t *app); /** Close bit matrix. @param b Bit matrix to close. */ void dk3bm_close(dk3_bm_t *b); /** Set or reset one bit. @param b Bit matrix. @param x Column number. @param y Row number. @param v New value for bit. */ void dk3bm_set(dk3_bm_t *b, size_t x, size_t y, int v); /** Get one bit. @param b Bit matrix. @param x Column number. @param y Row number. @return 1 or 0 depending on the bit value. */ int dk3bm_get(dk3_bm_t *b, size_t x, size_t y); /** Expand bit matrix. The matrix must be square. @param b Bit matrix. */ void dk3bm_expand(dk3_bm_t *b); #ifdef __cplusplus } #endif %% module #include "dk3all.h" $!trace-include /** Bit mask to set/retrieve single bits in a byte. */ static unsigned char const bits_in_byte[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; void dk3bf_close(dk3_bf_t *b) { if(b) { dk3_release(b->data) b->nbits = 0; b->app = NULL; dk3_delete(b); } } dk3_bf_t * dk3bf_open_app(size_t nbits, dk3_app_t *app) { dk3_bf_t *back = NULL; size_t sz = 0; /* Number of bytes needed. */ if(nbits) { sz = nbits / 8; if(nbits % 8) { sz++; } back = dk3_new_app(dk3_bf_t,1,app); if(back) { back->nbits = nbits; back->data = NULL; back->app = app; back->data = dk3_new_app(unsigned char,sz,app); if(back->data) { dk3mem_res((void *)(back->data), sz); } else { dk3bf_close(back); back = NULL; } } } return back; } void dk3bf_set(dk3_bf_t *b, size_t n, int v) { size_t byteno = 0; /* Byte index in data. */ size_t inbyte = 0; /* Number of bit within the byte. */ if(b) { if(n < b->nbits) { byteno = n / 8; inbyte = n % 8; if(v) { (b->data)[byteno] |= bits_in_byte[inbyte]; } else { (b->data)[byteno] &= (~(bits_in_byte[inbyte])); } } else { if(b->app) { /* ERROR: Index out of range. */ dk3app_log_i1(b->app, DK3_LL_ERROR, 200); } } } } int dk3bf_get(dk3_bf_t *b, size_t n) { int back = 0; size_t byteno = 0; /* Byte index in data. */ size_t inbyte = 0; /* Number of bit within the byte. */ if(b) { if(n < b->nbits) { byteno = n / 8; inbyte = n % 8; if(((b->data)[byteno]) & (bits_in_byte[inbyte])) { back = 1; } } else { if(b->app) { /* ERROR: Index out of range. */ dk3app_log_i1(b->app, DK3_LL_ERROR, 200); } } } return back; } void dk3bm_close(dk3_bm_t *b) { size_t i = 0; /* Index of current row to delete. */ if(b) { if(b->data) { for(i = 0; i < b->rows; i++) { dk3_release((b->data)[i]) } dk3_delete(b->data); } b->data = NULL; b->app = NULL; b->columns = 0; b->rows = 0; dk3_delete(b); } } dk3_bm_t * dk3bm_open(size_t x, size_t y, dk3_app_t *app) { size_t bytes_per_row = 0; /* Number of bytes per row. */ size_t i = 0; /* Current row to initialize. */ int ok = 0; /* Flag: Success. */ dk3_bm_t *back = NULL; if((x) && (y)) { back = dk3_new_app(dk3_bm_t,1,app); if(back) { back->columns = x; back->rows = y; back->app = app; back->data = NULL; bytes_per_row = x / 8; if(x % 8) { bytes_per_row++; } back->data = dk3_new_app(DK3_PUCHAR,y,app); if(back->data) { ok = 1; for(i = 0; i < y; i++) { (back->data)[i] = NULL; } for(i = 0; i < y; i++) { (back->data)[i] = dk3_new_app(unsigned char,bytes_per_row,app); if((back->data)[i]) { dk3mem_res((void *)((back->data)[i]), bytes_per_row); } else { ok = 0; } } if(ok == 0) { dk3bm_close(back); back = NULL; } } else { dk3_delete(back); back = NULL; } } } return back; } void dk3bm_set(dk3_bm_t *b, size_t x, size_t y, int v) { unsigned char *pu = NULL; /* Row pointer. */ size_t byteno = 0; /* Index of byte in row. */ size_t bitno = 0; /* Index of bit within the byte. */ if(b) { if((x < b->columns) && (y < b->rows)) { pu = (b->data)[y]; byteno = x / 8; bitno = x % 8; if(v) { pu[byteno] |= bits_in_byte[bitno]; } else { pu[byteno] &= (~(bits_in_byte[bitno])); } } } } int dk3bm_get(dk3_bm_t *b, size_t x, size_t y) { int back = 0; unsigned char *pu = NULL; /* Row pointer. */ size_t byteno = 0; /* Index of byte within the row. */ size_t bitno = 0; /* Index of bit within the byte. */ if(b) { if((x < b->columns) && (y < b->rows)) { pu = (b->data)[y]; byteno = x / 8; bitno = x % 8; if((pu[byteno]) & (bits_in_byte[bitno])) { back = 1; } } } return back; } void dk3bm_expand(dk3_bm_t *b) { int f_change_found = 0; /* Flag: Change found in this pass. */ size_t i = 0; /* Source node number. */ size_t j = 0; /* Destination node number. */ size_t k = 0; /* Intermediate node number. */ size_t p = 0; /* Number of current pass. */ if(b) { if(b->columns == b->rows) { p = 0; do { f_change_found = 0; for(i = 0; i < b->columns; i++) { for(j = 0; j < b->rows; j++) { if(!dk3bm_get(b, i, j)) { for(k = 0; k < b->columns; k++) { if(dk3bm_get(b, i, k)) { if(dk3bm_get(b, k, j)) { dk3bm_set(b, i, j, 1); f_change_found = 1; } } } } } } p++; } while((f_change_found) && (p < b->columns)); } else { if(b->app) { /* ERROR: Matrix must be a square! */ dk3app_log_i1(b->app, DK3_LL_ERROR, 201); } } } } /* vim: set ai sw=2 : */