summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bits.c16
-rw-r--r--bits_test.c11
2 files changed, 17 insertions, 10 deletions
diff --git a/bits.c b/bits.c
index 9f97ac5a..a2da1098 100644
--- a/bits.c
+++ b/bits.c
@@ -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");
}