Added SILC Bit Operations API.
[crypto.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 || pos >= bitmap_size)
34     return FALSE;
35
36   bitmap[pos] |= mask;
37   return TRUE;
38 }
39
40 /* Clear bit */
41
42 SilcBool silc_bit_clear(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
43                         SilcUInt32 bit)
44 {
45   SilcUInt32 pos = SILC_BIT_POS(bit);
46   unsigned long mask = SILC_BIT_MASK(bit);
47
48   if (!bitmap || pos >= bitmap_size)
49     return FALSE;
50
51   bitmap[pos] &= ~mask;
52   return TRUE;
53 }
54
55 /* Toggle bit */
56
57 SilcBool silc_bit_toggle(volatile unsigned long *bitmap,
58                          SilcUInt32 bitmap_size, SilcUInt32 bit)
59 {
60   SilcUInt32 pos = SILC_BIT_POS(bit);
61   unsigned long mask = SILC_BIT_MASK(bit);
62
63   if (!bitmap || pos >= bitmap_size)
64     return FALSE;
65
66   bitmap[pos] ^= mask;
67   return TRUE;
68 }
69
70 /* Set bit and return old value */
71
72 int silc_bit_test_and_set(volatile unsigned long *bitmap,
73                           SilcUInt32 bitmap_size, SilcUInt32 bit)
74 {
75   SilcUInt32 pos = SILC_BIT_POS(bit);
76   unsigned long mask = SILC_BIT_MASK(bit), ret;
77
78   if (!bitmap || pos >= bitmap_size)
79     return -1;
80
81   ret = bitmap[pos];
82   bitmap[pos] ^= mask;
83
84   return (ret & mask) != 0;
85 }
86
87 /* Clear bit and return old value */
88
89 int silc_bit_test_and_clear(volatile unsigned long *bitmap,
90                             SilcUInt32 bitmap_size, SilcUInt32 bit)
91 {
92   SilcUInt32 pos = SILC_BIT_POS(bit);
93   unsigned long mask = SILC_BIT_MASK(bit), ret;
94
95   if (!bitmap || pos >= bitmap_size)
96     return -1;
97
98   ret = bitmap[pos];
99   bitmap[pos] &= ~mask;
100
101   return (ret & mask) != 0;
102 }
103
104 /* Toggle bit and return old value */
105
106 int silc_bit_test_and_toggle(volatile unsigned long *bitmap,
107                              SilcUInt32 bitmap_size, SilcUInt32 bit)
108 {
109   SilcUInt32 pos = SILC_BIT_POS(bit);
110   unsigned long mask = SILC_BIT_MASK(bit), ret;
111
112   if (!bitmap || pos >= bitmap_size)
113     return -1;
114
115   ret = bitmap[pos];
116   bitmap[pos] ^= mask;
117
118   return (ret & mask) != 0;
119 }
120
121 /* Return bit value */
122
123 int silc_bit_get(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
124                  SilcUInt32 bit)
125 {
126   SilcUInt32 pos = SILC_BIT_POS(bit);
127   unsigned long mask = SILC_BIT_MASK(bit);
128
129   if (!bitmap || pos >= bitmap_size)
130     return -1;
131
132   return (bitmap[pos] & mask) != 0;
133 }
134
135 /* Return first set bit number */
136
137 int silc_bit_ffs(volatile unsigned long *bitmap, SilcUInt32 bitmap_size)
138 {
139   return silc_bit_fns(bitmap, bitmap_size, 0);
140 }
141
142 /* Return first zero bit number */
143
144 int silc_bit_ffz(volatile unsigned long *bitmap, SilcUInt32 bitmap_size)
145 {
146   return silc_bit_fnz(bitmap, bitmap_size, 0);
147 }
148
149 /* Return next set bit number */
150
151 int silc_bit_fns(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
152                  SilcUInt32 offset)
153 {
154   register SilcUInt32 i;
155
156   if (!bitmap || offset >= bitmap_size * SILC_BIT_SIZE)
157     return -1;
158
159   for (i = offset; i < bitmap_size * SILC_BIT_SIZE; i++)
160     if (bitmap[SILC_BIT_POS(i)] & SILC_BIT_MASK(i))
161       return i;
162
163   return -1;
164 }
165
166 /* Return next zero bit number */
167
168 int silc_bit_fnz(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
169                  SilcUInt32 offset)
170 {
171   register SilcUInt32 i;
172
173   if (!bitmap || offset >= bitmap_size * SILC_BIT_SIZE)
174     return -1;
175
176   for (i = offset; i < bitmap_size * SILC_BIT_SIZE; i++)
177     if ((bitmap[SILC_BIT_POS(i)] & SILC_BIT_MASK(i)) == 0)
178       return i;
179
180   return -1;
181 }
182
183 /* Clear bitmap */
184
185 void silc_bit_clear_bitmap(volatile unsigned long *bitmap,
186                            SilcUInt32 bitmap_size)
187 {
188   if (!bitmap)
189     return;
190   memset((void *)bitmap, 0, bitmap_size * 8);
191 }