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