diff options
-rw-r--r-- | bits.c | 16 | ||||
-rw-r--r-- | bits_test.c | 11 |
2 files changed, 17 insertions, 10 deletions
@@ -25,21 +25,25 @@ unsigned long long ubits(char buf[], unsigned int start, unsigned int width) unsigned int i;; assert(width <= sizeof(long long) * BITS_PER_BYTE); - for (i = 0; i < (width + BITS_PER_BYTE - 1) / BITS_PER_BYTE; i++) { + for (i = start / BITS_PER_BYTE; i < (start + width + BITS_PER_BYTE - 1) / BITS_PER_BYTE; i++) { fld <<= BITS_PER_BYTE; - fld |= (unsigned char)buf[start / BITS_PER_BYTE + i]; + fld |= (unsigned char)buf[i]; } #ifdef DEBUG printf("Extracting %d:%d from %s: segment 0x%llx = %lld\n", start, width, gpsd_hexdump(buf, 12), fld, fld); #endif /* DEBUG */ - fld &= (0xffffffff >> (start % BITS_PER_BYTE)); + fld >>= (BITS_PER_BYTE - ((start + width) % BITS_PER_BYTE)); #ifdef DEBUG - printf("After masking: 0x%llx = %lld\n", fld, fld); + printf("After downshifting by %d bits: 0x%llx = %lld\n", + (BITS_PER_BYTE - ((start + width) % BITS_PER_BYTE)), + fld, fld); #endif /* DEBUG */ - fld >>= (BITS_PER_BYTE - 1) - ((start + width) % BITS_PER_BYTE); + + fld &= ~(0xffffffff << width); #ifdef DEBUG - printf("After downshifting: 0x%llx = %lld\n", fld, fld); + printf("After selecting out the bottom %u bits: 0x%llx = %lld\n", + width, fld, fld); #endif /* DEBUG */ return fld; diff --git a/bits_test.c b/bits_test.c index 3273c1f1..63cfdf21 100644 --- a/bits_test.c +++ b/bits_test.c @@ -86,14 +86,17 @@ static void ledumpall(void) struct unsigned_test { unsigned int start, width; unsigned long long expected; + char *description; }; /*@ -duplicatequals +ignorequals @*/ int main(void) { struct unsigned_test *up, unsigned_tests[] = { - {0, 1, 0}, /* first bit of first byte */ - {0, 7, 1}, /* third bit of first byte */ + {0, 1, 0, "first bit of first byte"}, + {32, 7, 2, "first seven bits of fifth byte"}, + {56, 12, 0x8f, "12 bits crossing 7th to 8th bytes (08ff)"}, + {78, 4, 11, "2 bits crossing 8th to 9th byte (fefd)"}, }; unsigned char *sp; @@ -158,8 +161,8 @@ int main(void) up < unsigned_tests+sizeof(unsigned_tests)/sizeof(unsigned_tests[0]); up++) { unsigned long long res = ubits((char *)buf, up->start, up->width); - (void)printf("ubits(..., %d, %d) should be %llu, is %llu: %s\n", - up->start, up->width, up->expected, res, + (void)printf("ubits(..., %d, %d) %s should be %llu, is %llu: %s\n", + up->start, up->width, up->description, up->expected, res, res == up->expected ? "succeeded" : "FAILED"); } |