1 | /*************************************** 2 | $Revision: 1.12 $ 3 | 4 | bitmask (ma) - bitmask.c - library for manipulating fixed size bitmasks. 5 | 6 | Status: NOT REVUED, TESTED, INCOMPLETE 7 | 8 | Design and implementation by: Marek Bukowy, Chris Ottrey. 9 | 10 | ******************/ /****************** 11 | Copyright (c) 1999 RIPE NCC 12 | 13 | All Rights Reserved 14 | 15 | Permission to use, copy, modify, and distribute this software and its 16 | documentation for any purpose and without fee is hereby granted, 17 | provided that the above copyright notice appear in all copies and that 18 | both that copyright notice and this permission notice appear in 19 | supporting documentation, and that the name of the author not be 20 | used in advertising or publicity pertaining to distribution of the 21 | software without specific, written prior permission. 22 | 23 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 25 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 26 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 27 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 28 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 29 | ***************************************/ 30 | 31 | 32 | 33 | #include <stdio.h> 34 | #include <stdarg.h> 35 | #include <stdlib.h> 36 | #include <assert.h> 37 | 38 | #include <string.h> 39 | 40 | #include "bitmask.h" 41 | #include "memwrap.h" 42 | #include "globaldefs.h" 43 | 44 | int MA_isset(mask_t d, unsigned b) { 45 | return( 46 | (d.data[b / MASK_BITS_BASESIZE] &(1 <<(b % MASK_BITS_BASESIZE))) 47 | > 0); 48 | } 49 | 50 | void MA_set(mask_t *m_ptr, unsigned b, unsigned v) { 51 | assert(b < MASK_MAX); 52 | assert(v == 0 || v == 1); 53 | 54 | if(v == 1) 55 | m_ptr->data[b / MASK_BITS_BASESIZE] |=(1 <<(b % MASK_BITS_BASESIZE)); 56 | else 57 | m_ptr->data[b / MASK_BITS_BASESIZE] &= ~(1 <<(b % MASK_BITS_BASESIZE)); 58 | } 59 | 60 | void MA_clear(mask_t *m_ptr) { 61 | memset(m_ptr, 0, sizeof(mask_t)); 62 | } /* MA_clear() */ 63 | 64 | 65 | /* set bits in dptr. variable number of args, terminated by MA_END 66 | 67 | MA_END is -1, so the arguments are of type signed int 68 | */ 69 | mask_t MA_new(int n,...) { 70 | va_list ap; 71 | mask_t d; 72 | 73 | MA_clear(&d); 74 | 75 | /* cover the "empty mask" case => MA_new(MA_END) invoked */ 76 | for ( va_start(ap, n); n != MA_END; n = va_arg(ap, int) ) { 77 | MA_set(&d, (unsigned) n, 1); 78 | } 79 | va_end(ap); 80 | 81 | return d; 82 | } 83 | 84 | 85 | void MA_prt(mask_t m) { 86 | unsigned i; 87 | 88 | for (i = 0; i < MASK_MAX; i++) { 89 | printf("%d", MA_isset(m, i)); 90 | } 91 | 92 | printf("\n"); 93 | 94 | for (i = 0; i < MASK_BITS_WORDS; i++) { 95 | printf("0x%0*X ", 2 * sizeof(MASK_BITS_BASETYPE), m.data[i]); 96 | } 97 | 98 | printf("\n"); 99 | } 100 | 101 | /* Perform a logical AND on two masks. 102 | Author: ottrey 103 | Date: Tue Jul 6 13:28:24 CEST 1999 104 | NB: This operation could/should be done a word at a time? 105 | */ 106 | mask_t MA_and(mask_t a, mask_t b) { 107 | mask_t c; 108 | unsigned i; 109 | 110 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 111 | c.data[i] = a.data[i] & b.data[i]; 112 | } 113 | return c; 114 | } /* MA_and() */ 115 | 116 | /* Perform a logical XOR on two masks. 117 | Author: ottrey 118 | Date: Thu Jul 8 14:50:14 CEST 1999 119 | NB: This operation could/should be done a word at a time? 120 | */ 121 | mask_t MA_xor(mask_t a, mask_t b) { 122 | mask_t c; 123 | unsigned i; 124 | 125 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 126 | c.data[i] = a.data[i] ^ b.data[i]; 127 | } 128 | 129 | return c; 130 | 131 | } /* MA_xor() */ 132 | 133 | /* Perform a logical OR on two masks. 134 | Author: ottrey 135 | Date: Thu Jul 8 16:34:34 CEST 1999 136 | NB: This operation could/should be done a word at a time? 137 | */ 138 | mask_t MA_or(mask_t a, mask_t b) { 139 | mask_t c; 140 | unsigned i; 141 | 142 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 143 | c.data[i] = a.data[i] | b.data[i]; 144 | } 145 | 146 | return c; 147 | 148 | } /* MA_or() */ 149 | 150 | /* Perform a logical NOT operation on a mask. 151 | Author: marek 152 | Date: Fri Jan 14 17:15:00 MET 2000 153 | NB: This operation is done a word at a time. 154 | */ 155 | mask_t MA_not(mask_t a) { 156 | mask_t c; 157 | unsigned i; 158 | 159 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 160 | c.data[i] = ~a.data[i]; 161 | } 162 | return c; 163 | } 164 | 165 | /* Counts the number of bits set. */ 166 | int MA_bitcount(mask_t m) { 167 | unsigned i; 168 | int count=0; 169 | 170 | for (i=0; i < MASK_MAX; i++) { 171 | count += MA_isset(m, i); 172 | } 173 | 174 | return count; 175 | 176 | } /* MA_bitcount() */ 177 | 178 | /* Convert the bitmap to a string comprising of tokens from an array of tokens. 179 | Author: ottrey 180 | Date: Tue Jul 6 13:28:24 CEST 1999 181 | */ 182 | char *MA_to_string(mask_t mask, char * const *tokens) { 183 | char *str; 184 | char str_buf[STR_L]; 185 | int count; 186 | unsigned i; 187 | int length; 188 | 189 | strcpy(str_buf, ""); 190 | 191 | count=0; 192 | sprintf(str_buf, "{"); 193 | for (i=0; tokens[i] != NULL; i++) { 194 | if ( MA_isset(mask, i) != 0) { 195 | strcat(str_buf, tokens[i]); 196 | strcat(str_buf, ","); 197 | count++; 198 | } 199 | } 200 | if (count == 0) { 201 | strcat(str_buf, "NULL "); 202 | } 203 | length = strlen(str_buf); 204 | str_buf[length-1] = '}'; 205 | 206 | /* str = (char *)calloc(1, strlen(str_buf)+1); */ 207 | dieif(wr_calloc( (void **) &str, 1, strlen(str_buf)+1) != UT_OK); 208 | 209 | strcpy(str, str_buf); 210 | 211 | return str; 212 | 213 | } /* MA_to_string() */ 214 | 215 | #ifdef MODULE_TEST 216 | void 217 | main() { 218 | mask_t d; 219 | 220 | d = MA_new(1, 4, 56, 3, 5, 7, 19, MA_END); 221 | 222 | MA_prt(d); 223 | 224 | MA_set(&d, 3, 0); 225 | MA_set(&d, 7, 0); 226 | MA_set(&d, 9, 0); 227 | MA_set(&d, 19, 0); 228 | 229 | MA_prt(d); 230 | } 231 | #endif