mouse@thunder.mcrcim.mcgill.edu (der Mouse) (03/15/91)
In article <788@llnl.LLNL.GOV>, handeli@ocfmail.ocf.llnl.gov writes: > I need a C function which can move arbitrary bits around from one > memory location to another with a bit offset of anything. For > example, the call might look like > movebits(a1,ioff1,a2,ioff2,nbits) This really belongs in a C group. I have cross-posted to comp.lang.c and am redirecting followups there. I am assuming that the bits in a byte are taken LSB-first, so that an offset of 9, for example, skips the first byte and the LSB of the second byte. To switch this, fiddle with some of the shift operations. Warning: untested. Assumes that the number of bits in an unsigned int is no less than one less than twice the number of bits in an unsigned char (most machines will have no trouble with this restraint). Optimization possibilities abound. #define CHAR_BITS 8 /* or whatever: # of bits in unsigned char */ movebits(a1,ioff1,a2,ioff2,nbits) unsigned char *a1; /* from */ unsigned int ioff1; unsigned char *a2; /* to */ unsigned int ioff2; unsigned int nbits; { unsigned int buf; unsigned char mask; int have; if (nbits < 1) return; /* careful: don't read *a1 in this case */ a1 += ioff1 / CHAR_BITS; ioff1 %= CHAR_BITS; a2 += ioff2 / CHAR_BITS; ioff2 %= CHAR_BITS; buf = *a1++; have = CHAR_BITS - ioff1; buf >>= ioff1; while (nbits > 0) { if ((have < CHAR_BITS) && (nbits > have)) { buf |= *a1++ << have; have += CHAR_BITS; } if (ioff2+nbits < CHAR_BITS) { mask = ((1 << nbits) - 1) << ioff2; } else { mask = (~0) << ioff2; } *a2 = (*a2 & ~mask) | ((buf << ioff2) & mask); a2 ++; buf >>= CHAR_BITS - ioff2; have -= CHAR_BITS - ioff2; nbits -= CHAR_BITS - ioff2; ioff2 = 0; } } der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu