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