Added SILC Thread Queue API
[silc.git] / lib / silcutil / silcbitops.c
1 /*
2
3   silcbitops.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silc.h"
21
22 #define SILC_BIT_POS(bit) (bit / SILC_BIT_SIZE)
23 #define SILC_BIT_MASK(bit) (1UL << (bit % SILC_BIT_SIZE))
24
25 /* Set bit */
26
27 SilcBool silc_bit_set(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
28                       SilcUInt32 bit)
29 {
30   SilcUInt32 pos = SILC_BIT_POS(bit);
31   unsigned long mask = SILC_BIT_MASK(bit);
32
33   if (!bitmap) {
34     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
35     return FALSE;
36   }
37   if (pos >= bitmap_size) {
38     silc_set_errno(SILC_ERR_OVERFLOW);
39     return FALSE;
40   }
41
42   bitmap[pos] |= mask;
43   return TRUE;
44 }
45
46 /* Clear bit */
47
48 SilcBool silc_bit_clear(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
49                         SilcUInt32 bit)
50 {
51   SilcUInt32 pos = SILC_BIT_POS(bit);
52   unsigned long mask = SILC_BIT_MASK(bit);
53
54   if (!bitmap) {
55     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
56     return FALSE;
57   }
58   if (pos >= bitmap_size) {
59     silc_set_errno(SILC_ERR_OVERFLOW);
60     return FALSE;
61   }
62
63   bitmap[pos] &= ~mask;
64   return TRUE;
65 }
66
67 /* Toggle bit */
68
69 SilcBool silc_bit_toggle(volatile unsigned long *bitmap,
70                          SilcUInt32 bitmap_size, SilcUInt32 bit)
71 {
72   SilcUInt32 pos = SILC_BIT_POS(bit);
73   unsigned long mask = SILC_BIT_MASK(bit);
74
75   if (!bitmap) {
76     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
77     return FALSE;
78   }
79   if (pos >= bitmap_size) {
80     silc_set_errno(SILC_ERR_OVERFLOW);
81     return FALSE;
82   }
83
84   bitmap[pos] ^= mask;
85   return TRUE;
86 }
87
88 /* Set bit and return old value */
89
90 int silc_bit_test_and_set(volatile unsigned long *bitmap,
91                           SilcUInt32 bitmap_size, SilcUInt32 bit)
92 {
93   SilcUInt32 pos = SILC_BIT_POS(bit);
94   unsigned long mask = SILC_BIT_MASK(bit), ret;
95
96   if (!bitmap) {
97     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
98     return -1;
99   }
100   if (pos >= bitmap_size) {
101     silc_set_errno(SILC_ERR_OVERFLOW);
102     return -1;
103   }
104
105   ret = bitmap[pos];
106   bitmap[pos] ^= mask;
107
108   return (ret & mask) != 0;
109 }
110
111 /* Clear bit and return old value */
112
113 int silc_bit_test_and_clear(volatile unsigned long *bitmap,
114                             SilcUInt32 bitmap_size, SilcUInt32 bit)
115 {
116   SilcUInt32 pos = SILC_BIT_POS(bit);
117   unsigned long mask = SILC_BIT_MASK(bit), ret;
118
119   if (!bitmap) {
120     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
121     return -1;
122   }
123   if (pos >= bitmap_size) {
124     silc_set_errno(SILC_ERR_OVERFLOW);
125     return -1;
126   }
127
128   ret = bitmap[pos];
129   bitmap[pos] &= ~mask;
130
131   return (ret & mask) != 0;
132 }
133
134 /* Toggle bit and return old value */
135
136 int silc_bit_test_and_toggle(volatile unsigned long *bitmap,
137                              SilcUInt32 bitmap_size, SilcUInt32 bit)
138 {
139   SilcUInt32 pos = SILC_BIT_POS(bit);
140   unsigned long mask = SILC_BIT_MASK(bit), ret;
141
142   if (!bitmap) {
143     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
144     return -1;
145   }
146   if (pos >= bitmap_size) {
147     silc_set_errno(SILC_ERR_OVERFLOW);
148     return -1;
149   }
150
151   ret = bitmap[pos];
152   bitmap[pos] ^= mask;
153
154   return (ret & mask) != 0;
155 }
156
157 /* Return bit value */
158
159 int silc_bit_get(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
160                  SilcUInt32 bit)
161 {
162   SilcUInt32 pos = SILC_BIT_POS(bit);
163   unsigned long mask = SILC_BIT_MASK(bit);
164
165   if (!bitmap) {
166     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
167     return -1;
168   }
169   if (pos >= bitmap_size) {
170     silc_set_errno(SILC_ERR_OVERFLOW);
171     return -1;
172   }
173
174   return (bitmap[pos] & mask) != 0;
175 }
176
177 /* Return first set bit number */
178
179 int silc_bit_ffs(volatile unsigned long *bitmap, SilcUInt32 bitmap_size)
180 {
181   return silc_bit_fns(bitmap, bitmap_size, 0);
182 }
183
184 /* Return first zero bit number */
185
186 int silc_bit_ffz(volatile unsigned long *bitmap, SilcUInt32 bitmap_size)
187 {
188   return silc_bit_fnz(bitmap, bitmap_size, 0);
189 }
190
191 /* Return next set bit number */
192
193 int silc_bit_fns(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
194                  SilcUInt32 offset)
195 {
196   register SilcUInt32 i;
197
198   if (!bitmap) {
199     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
200     return -1;
201   }
202   if (offset >= bitmap_size * SILC_BIT_SIZE) {
203     silc_set_errno(SILC_ERR_OVERFLOW);
204     return -1;
205   }
206
207   for (i = offset; i < bitmap_size * SILC_BIT_SIZE; i++)
208     if (bitmap[SILC_BIT_POS(i)] & SILC_BIT_MASK(i))
209       return i;
210
211   silc_set_errno(SILC_ERR_NOT_FOUND);
212   return -1;
213 }
214
215 /* Return next zero bit number */
216
217 int silc_bit_fnz(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
218                  SilcUInt32 offset)
219 {
220   register SilcUInt32 i;
221
222   if (!bitmap) {
223     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
224     return -1;
225   }
226   if (offset >= bitmap_size * SILC_BIT_SIZE) {
227     silc_set_errno(SILC_ERR_OVERFLOW);
228     return -1;
229   }
230
231   for (i = offset; i < bitmap_size * SILC_BIT_SIZE; i++)
232     if ((bitmap[SILC_BIT_POS(i)] & SILC_BIT_MASK(i)) == 0)
233       return i;
234
235   silc_set_errno(SILC_ERR_NOT_FOUND);
236   return -1;
237 }
238
239 /* Clear bitmap */
240
241 void silc_bit_clear_bitmap(volatile unsigned long *bitmap,
242                            SilcUInt32 bitmap_size)
243 {
244   if (!bitmap)
245     return;
246   memset((void *)bitmap, 0, bitmap_size * 8);
247 }