[PATCH] DVB: Documentation and Kconfig updazes
[linux-2.6/history.git] / lib / bitmap.c
blob6793ac0029151ab3b0bfb8a3df7014cf79d06b0f
1 /*
2 * lib/bitmap.c
3 * Helper functions for bitmap.h.
5 * This source code is licensed under the GNU General Public License,
6 * Version 2. See the file COPYING for more details.
7 */
8 #include <linux/module.h>
9 #include <linux/ctype.h>
10 #include <linux/errno.h>
11 #include <linux/bitmap.h>
12 #include <asm/bitops.h>
13 #include <asm/uaccess.h>
15 #define MAX_BITMAP_BITS 512U /* for ia64 NR_CPUS maximum */
17 int bitmap_empty(const unsigned long *bitmap, int bits)
19 int k, lim = bits/BITS_PER_LONG;
20 for (k = 0; k < lim; ++k)
21 if (bitmap[k])
22 return 0;
24 if (bits % BITS_PER_LONG)
25 if (bitmap[k] & ((1UL << (bits % BITS_PER_LONG)) - 1))
26 return 0;
28 return 1;
30 EXPORT_SYMBOL(bitmap_empty);
32 int bitmap_full(const unsigned long *bitmap, int bits)
34 int k, lim = bits/BITS_PER_LONG;
35 for (k = 0; k < lim; ++k)
36 if (~bitmap[k])
37 return 0;
39 if (bits % BITS_PER_LONG)
40 if (~bitmap[k] & ((1UL << (bits % BITS_PER_LONG)) - 1))
41 return 0;
43 return 1;
45 EXPORT_SYMBOL(bitmap_full);
47 int bitmap_equal(const unsigned long *bitmap1,
48 unsigned long *bitmap2, int bits)
50 int k, lim = bits/BITS_PER_LONG;
51 for (k = 0; k < lim; ++k)
52 if (bitmap1[k] != bitmap2[k])
53 return 0;
55 if (bits % BITS_PER_LONG)
56 if ((bitmap1[k] ^ bitmap2[k]) &
57 ((1UL << (bits % BITS_PER_LONG)) - 1))
58 return 0;
60 return 1;
62 EXPORT_SYMBOL(bitmap_equal);
64 void bitmap_complement(unsigned long *bitmap, int bits)
66 int k;
67 int nr = BITS_TO_LONGS(bits);
69 for (k = 0; k < nr; ++k)
70 bitmap[k] = ~bitmap[k];
72 EXPORT_SYMBOL(bitmap_complement);
74 void bitmap_shift_right(unsigned long *dst,
75 const unsigned long *src, int shift, int bits)
77 int k;
78 DECLARE_BITMAP(__shr_tmp, MAX_BITMAP_BITS);
80 BUG_ON(bits > MAX_BITMAP_BITS);
81 bitmap_clear(__shr_tmp, bits);
82 for (k = 0; k < bits - shift; ++k)
83 if (test_bit(k + shift, src))
84 set_bit(k, __shr_tmp);
85 bitmap_copy(dst, __shr_tmp, bits);
87 EXPORT_SYMBOL(bitmap_shift_right);
89 void bitmap_shift_left(unsigned long *dst,
90 const unsigned long *src, int shift, int bits)
92 int k;
93 DECLARE_BITMAP(__shl_tmp, MAX_BITMAP_BITS);
95 BUG_ON(bits > MAX_BITMAP_BITS);
96 bitmap_clear(__shl_tmp, bits);
97 for (k = bits; k >= shift; --k)
98 if (test_bit(k - shift, src))
99 set_bit(k, __shl_tmp);
100 bitmap_copy(dst, __shl_tmp, bits);
102 EXPORT_SYMBOL(bitmap_shift_left);
104 void bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
105 const unsigned long *bitmap2, int bits)
107 int k;
108 int nr = BITS_TO_LONGS(bits);
110 for (k = 0; k < nr; k++)
111 dst[k] = bitmap1[k] & bitmap2[k];
113 EXPORT_SYMBOL(bitmap_and);
115 void bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
116 const unsigned long *bitmap2, int bits)
118 int k;
119 int nr = BITS_TO_LONGS(bits);
121 for (k = 0; k < nr; k++)
122 dst[k] = bitmap1[k] | bitmap2[k];
124 EXPORT_SYMBOL(bitmap_or);
126 #if BITS_PER_LONG == 32
127 int bitmap_weight(const unsigned long *bitmap, int bits)
129 int k, w = 0, lim = bits/BITS_PER_LONG;
131 for (k = 0; k < lim; k++)
132 w += hweight32(bitmap[k]);
134 if (bits % BITS_PER_LONG)
135 w += hweight32(bitmap[k] &
136 ((1UL << (bits % BITS_PER_LONG)) - 1));
138 return w;
140 #else
141 int bitmap_weight(const unsigned long *bitmap, int bits)
143 int k, w = 0, lim = bits/BITS_PER_LONG;
145 for (k = 0; k < lim; k++)
146 w += hweight64(bitmap[k]);
148 if (bits % BITS_PER_LONG)
149 w += hweight64(bitmap[k] &
150 ((1UL << (bits % BITS_PER_LONG)) - 1));
152 return w;
154 #endif
155 EXPORT_SYMBOL(bitmap_weight);
158 * Bitmap printing & parsing functions: first version by Bill Irwin,
159 * second version by Paul Jackson, third by Joe Korty.
162 #define CHUNKSZ 32
163 #define nbits_to_hold_value(val) fls(val)
164 #define roundup_power2(val,modulus) (((val) + (modulus) - 1) & ~((modulus) - 1))
165 #define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
168 * bitmap_scnprintf - convert bitmap to an ASCII hex string.
169 * @buf: byte buffer into which string is placed
170 * @buflen: reserved size of @buf, in bytes
171 * @maskp: pointer to bitmap to convert
172 * @nmaskbits: size of bitmap, in bits
174 * Exactly @nmaskbits bits are displayed. Hex digits are grouped into
175 * comma-separated sets of eight digits per set.
177 int bitmap_scnprintf(char *buf, unsigned int buflen,
178 const unsigned long *maskp, int nmaskbits)
180 int i, word, bit, len = 0;
181 unsigned long val;
182 const char *sep = "";
183 int chunksz;
184 u32 chunkmask;
186 chunksz = nmaskbits & (CHUNKSZ - 1);
187 if (chunksz == 0)
188 chunksz = CHUNKSZ;
190 i = roundup_power2(nmaskbits, CHUNKSZ) - CHUNKSZ;
191 for (; i >= 0; i -= CHUNKSZ) {
192 chunkmask = ((1ULL << chunksz) - 1);
193 word = i / BITS_PER_LONG;
194 bit = i % BITS_PER_LONG;
195 val = (maskp[word] >> bit) & chunkmask;
196 len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
197 (chunksz+3)/4, val);
198 chunksz = CHUNKSZ;
199 sep = ",";
201 return len;
203 EXPORT_SYMBOL(bitmap_scnprintf);
206 * bitmap_parse - convert an ASCII hex string into a bitmap.
207 * @buf: pointer to buffer in user space containing string.
208 * @buflen: buffer size in bytes. If string is smaller than this
209 * then it must be terminated with a \0.
210 * @maskp: pointer to bitmap array that will contain result.
211 * @nmaskbits: size of bitmap, in bits.
213 * Commas group hex digits into chunks. Each chunk defines exactly 32
214 * bits of the resultant bitmask. No chunk may specify a value larger
215 * than 32 bits (-EOVERFLOW), and if a chunk specifies a smaller value
216 * then leading 0-bits are prepended. -EINVAL is returned for illegal
217 * characters and for grouping errors such as "1,,5", ",44", "," and "".
218 * Leading and trailing whitespace accepted, but not embedded whitespace.
220 int bitmap_parse(const char __user *ubuf, unsigned int ubuflen,
221 unsigned long *maskp, int nmaskbits)
223 int c, old_c, totaldigits, ndigits, nchunks, nbits;
224 u32 chunk;
226 bitmap_clear(maskp, nmaskbits);
228 nchunks = nbits = totaldigits = c = 0;
229 do {
230 chunk = ndigits = 0;
232 /* Get the next chunk of the bitmap */
233 while (ubuflen) {
234 old_c = c;
235 if (get_user(c, ubuf++))
236 return -EFAULT;
237 ubuflen--;
238 if (isspace(c))
239 continue;
242 * If the last character was a space and the current
243 * character isn't '\0', we've got embedded whitespace.
244 * This is a no-no, so throw an error.
246 if (totaldigits && c && isspace(old_c))
247 return -EINVAL;
249 /* A '\0' or a ',' signal the end of the chunk */
250 if (c == '\0' || c == ',')
251 break;
253 if (!isxdigit(c))
254 return -EINVAL;
257 * Make sure there are at least 4 free bits in 'chunk'.
258 * If not, this hexdigit will overflow 'chunk', so
259 * throw an error.
261 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
262 return -EOVERFLOW;
264 chunk = (chunk << 4) | unhex(c);
265 ndigits++; totaldigits++;
267 if (ndigits == 0)
268 return -EINVAL;
269 if (nchunks == 0 && chunk == 0)
270 continue;
272 bitmap_shift_right(maskp, maskp, CHUNKSZ, nmaskbits);
273 *maskp |= chunk;
274 nchunks++;
275 nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
276 if (nbits > nmaskbits)
277 return -EOVERFLOW;
278 } while (ubuflen && c == ',');
280 return 0;
282 EXPORT_SYMBOL(bitmap_parse);