bitmap: Introduce bitmap_cut(): cut bits and shift remaining
The new bitmap function bitmap_cut() copies bits from source to destination by removing the region specified by parameters first and cut, and remapping the bits above the cut region by right shifting them. Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Родитель
f3a2181e16
Коммит
2092767168
|
@ -53,6 +53,7 @@
|
||||||
* bitmap_find_next_zero_area_off(buf, len, pos, n, mask) as above
|
* bitmap_find_next_zero_area_off(buf, len, pos, n, mask) as above
|
||||||
* bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
|
* bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
|
||||||
* bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
|
* bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
|
||||||
|
* bitmap_cut(dst, src, first, n, nbits) Cut n bits from first, copy rest
|
||||||
* bitmap_replace(dst, old, new, mask, nbits) *dst = (*old & ~(*mask)) | (*new & *mask)
|
* bitmap_replace(dst, old, new, mask, nbits) *dst = (*old & ~(*mask)) | (*new & *mask)
|
||||||
* bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
|
* bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
|
||||||
* bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit)
|
* bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit)
|
||||||
|
@ -133,6 +134,9 @@ extern void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
|
||||||
unsigned int shift, unsigned int nbits);
|
unsigned int shift, unsigned int nbits);
|
||||||
extern void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
|
extern void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
|
||||||
unsigned int shift, unsigned int nbits);
|
unsigned int shift, unsigned int nbits);
|
||||||
|
extern void bitmap_cut(unsigned long *dst, const unsigned long *src,
|
||||||
|
unsigned int first, unsigned int cut,
|
||||||
|
unsigned int nbits);
|
||||||
extern int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
extern int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
const unsigned long *bitmap2, unsigned int nbits);
|
const unsigned long *bitmap2, unsigned int nbits);
|
||||||
extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
|
|
66
lib/bitmap.c
66
lib/bitmap.c
|
@ -168,6 +168,72 @@ void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__bitmap_shift_left);
|
EXPORT_SYMBOL(__bitmap_shift_left);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bitmap_cut() - remove bit region from bitmap and right shift remaining bits
|
||||||
|
* @dst: destination bitmap, might overlap with src
|
||||||
|
* @src: source bitmap
|
||||||
|
* @first: start bit of region to be removed
|
||||||
|
* @cut: number of bits to remove
|
||||||
|
* @nbits: bitmap size, in bits
|
||||||
|
*
|
||||||
|
* Set the n-th bit of @dst iff the n-th bit of @src is set and
|
||||||
|
* n is less than @first, or the m-th bit of @src is set for any
|
||||||
|
* m such that @first <= n < nbits, and m = n + @cut.
|
||||||
|
*
|
||||||
|
* In pictures, example for a big-endian 32-bit architecture:
|
||||||
|
*
|
||||||
|
* @src:
|
||||||
|
* 31 63
|
||||||
|
* | |
|
||||||
|
* 10000000 11000001 11110010 00010101 10000000 11000001 01110010 00010101
|
||||||
|
* | | | |
|
||||||
|
* 16 14 0 32
|
||||||
|
*
|
||||||
|
* if @cut is 3, and @first is 14, bits 14-16 in @src are cut and @dst is:
|
||||||
|
*
|
||||||
|
* 31 63
|
||||||
|
* | |
|
||||||
|
* 10110000 00011000 00110010 00010101 00010000 00011000 00101110 01000010
|
||||||
|
* | | |
|
||||||
|
* 14 (bit 17 0 32
|
||||||
|
* from @src)
|
||||||
|
*
|
||||||
|
* Note that @dst and @src might overlap partially or entirely.
|
||||||
|
*
|
||||||
|
* This is implemented in the obvious way, with a shift and carry
|
||||||
|
* step for each moved bit. Optimisation is left as an exercise
|
||||||
|
* for the compiler.
|
||||||
|
*/
|
||||||
|
void bitmap_cut(unsigned long *dst, const unsigned long *src,
|
||||||
|
unsigned int first, unsigned int cut, unsigned int nbits)
|
||||||
|
{
|
||||||
|
unsigned int len = BITS_TO_LONGS(nbits);
|
||||||
|
unsigned long keep = 0, carry;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memmove(dst, src, len * sizeof(*dst));
|
||||||
|
|
||||||
|
if (first % BITS_PER_LONG) {
|
||||||
|
keep = src[first / BITS_PER_LONG] &
|
||||||
|
(~0UL >> (BITS_PER_LONG - first % BITS_PER_LONG));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cut--) {
|
||||||
|
for (i = first / BITS_PER_LONG; i < len; i++) {
|
||||||
|
if (i < len - 1)
|
||||||
|
carry = dst[i + 1] & 1UL;
|
||||||
|
else
|
||||||
|
carry = 0;
|
||||||
|
|
||||||
|
dst[i] = (dst[i] >> 1) | (carry << (BITS_PER_LONG - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[first / BITS_PER_LONG] &= ~0UL << (first % BITS_PER_LONG);
|
||||||
|
dst[first / BITS_PER_LONG] |= keep;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(bitmap_cut);
|
||||||
|
|
||||||
int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
const unsigned long *bitmap2, unsigned int bits)
|
const unsigned long *bitmap2, unsigned int bits)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче