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