1 | /*************************************** 2 | $Revision: 1.15 $ 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,2000,2001,2002 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 "rip.h" 34 | 35 | #include <stdio.h> 36 | #include <stdarg.h> 37 | #include <stdlib.h> 38 | #include <assert.h> 39 | 40 | #include <string.h> 41 | 42 | int MA_isset(mask_t d, unsigned b) { 43 | return( 44 | (d.data[b / MASK_BITS_BASESIZE] &(1 <<(b % MASK_BITS_BASESIZE))) 45 | > 0); 46 | } 47 | 48 | void MA_set(mask_t *m_ptr, unsigned b, unsigned v) { 49 | assert(b < MASK_MAX); 50 | assert(v == 0 || v == 1); 51 | 52 | if(v == 1) 53 | m_ptr->data[b / MASK_BITS_BASESIZE] |=(1 <<(b % MASK_BITS_BASESIZE)); 54 | else 55 | m_ptr->data[b / MASK_BITS_BASESIZE] &= ~(1 <<(b % MASK_BITS_BASESIZE)); 56 | } 57 | 58 | void MA_clear(mask_t *m_ptr) { 59 | memset(m_ptr, 0, sizeof(mask_t)); 60 | } /* MA_clear() */ 61 | 62 | 63 | /* set bits in dptr. variable number of args, terminated by MA_END 64 | 65 | MA_END is -1, so the arguments are of type signed int 66 | */ 67 | mask_t MA_new(int n,...) { 68 | va_list ap; 69 | mask_t d; 70 | 71 | MA_clear(&d); 72 | 73 | /* cover the "empty mask" case => MA_new(MA_END) invoked */ 74 | for ( va_start(ap, n); n != MA_END; n = va_arg(ap, int) ) { 75 | MA_set(&d, (unsigned) n, 1); 76 | } 77 | va_end(ap); 78 | 79 | return d; 80 | } 81 | 82 | 83 | void MA_prt(mask_t m) { 84 | unsigned i; 85 | 86 | for (i = 0; i < MASK_MAX; i++) { 87 | printf("%d", MA_isset(m, i)); 88 | } 89 | 90 | printf("\n"); 91 | 92 | for (i = 0; i < MASK_BITS_WORDS; i++) { 93 | printf("0x%0*X ", 2 * (int)sizeof(MASK_BITS_BASETYPE), m.data[i]); 94 | } 95 | 96 | printf("\n"); 97 | } 98 | 99 | /* Perform a logical AND on two masks. 100 | Author: ottrey 101 | Date: Tue Jul 6 13:28:24 CEST 1999 102 | NB: This operation could/should be done a word at a time? 103 | */ 104 | mask_t MA_and(mask_t a, mask_t b) { 105 | mask_t c; 106 | unsigned i; 107 | 108 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 109 | c.data[i] = a.data[i] & b.data[i]; 110 | } 111 | return c; 112 | } /* MA_and() */ 113 | 114 | /* Perform a logical XOR on two masks. 115 | Author: ottrey 116 | Date: Thu Jul 8 14:50:14 CEST 1999 117 | NB: This operation could/should be done a word at a time? 118 | */ 119 | mask_t MA_xor(mask_t a, mask_t b) { 120 | mask_t c; 121 | unsigned i; 122 | 123 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 124 | c.data[i] = a.data[i] ^ b.data[i]; 125 | } 126 | 127 | return c; 128 | 129 | } /* MA_xor() */ 130 | 131 | /* Perform a logical OR on two masks. 132 | Author: ottrey 133 | Date: Thu Jul 8 16:34:34 CEST 1999 134 | NB: This operation could/should be done a word at a time? 135 | */ 136 | mask_t MA_or(mask_t a, mask_t b) { 137 | mask_t c; 138 | unsigned i; 139 | 140 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 141 | c.data[i] = a.data[i] | b.data[i]; 142 | } 143 | 144 | return c; 145 | 146 | } /* MA_or() */ 147 | 148 | /* Perform a logical NOT operation on a mask. 149 | Author: marek 150 | Date: Fri Jan 14 17:15:00 MET 2000 151 | NB: This operation is done a word at a time. 152 | */ 153 | mask_t MA_not(mask_t a) { 154 | mask_t c; 155 | unsigned i; 156 | 157 | for (i=0; i < MASK_BITS_WORDS; i++ ) { 158 | c.data[i] = ~a.data[i]; 159 | } 160 | return c; 161 | } 162 | 163 | /* Counts the number of bits set. */ 164 | int MA_bitcount(mask_t m) { 165 | unsigned i; 166 | int count=0; 167 | 168 | for (i=0; i < MASK_MAX; i++) { 169 | count += MA_isset(m, i); 170 | } 171 | 172 | return count; 173 | 174 | } /* MA_bitcount() */ 175 | 176 | /* Convert the bitmap to a string comprising of tokens from an array of tokens. 177 | Author: ottrey 178 | Date: Tue Jul 6 13:28:24 CEST 1999 179 | */ 180 | char *MA_to_string(mask_t mask, char * const *tokens) { 181 | char str_buf[STR_L]; 182 | int count; 183 | unsigned i; 184 | int length; 185 | 186 | count=0; 187 | strcpy(str_buf, "{"); 188 | for (i=0; tokens[i] != NULL; i++) { 189 | if ( MA_isset(mask, i) != 0) { 190 | strcat(str_buf, tokens[i]); 191 | strcat(str_buf, ","); 192 | count++; 193 | } 194 | } 195 | if (count == 0) { 196 | strcat(str_buf, "NULL "); 197 | } 198 | length = strlen(str_buf); 199 | str_buf[length-1] = '}'; 200 | 201 | return UT_strdup(str_buf); 202 | 203 | } /* MA_to_string() */ 204 | 205 | #ifdef MODULE_TEST 206 | void 207 | main() { 208 | mask_t d; 209 | 210 | d = MA_new(1, 4, 56, 3, 5, 7, 19, MA_END); 211 | 212 | MA_prt(d); 213 | 214 | MA_set(&d, 3, 0); 215 | MA_set(&d, 7, 0); 216 | MA_set(&d, 9, 0); 217 | MA_set(&d, 19, 0); 218 | 219 | MA_prt(d); 220 | } 221 | #endif