summaryrefslogtreecommitdiff
path: root/bits.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2008-07-17 15:21:53 +0000
committerEric S. Raymond <esr@thyrsus.com>2008-07-17 15:21:53 +0000
commita7e8a5ebcd3d22c0a046f0c83be761b681454937 (patch)
tree78caf8f90d8a0ee158658598fa6d7068167c930c /bits.c
parent65f2700670f1e3028ba949e2981583f88caa0d14 (diff)
downloadgpsd-a7e8a5ebcd3d22c0a046f0c83be761b681454937.tar.gz
Still more fixes for bitfield extraction.
This is as theoretically simple but difficult to get right as BitBlt.
Diffstat (limited to 'bits.c')
-rw-r--r--bits.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/bits.c b/bits.c
index a2da1098..ae5a4a2b 100644
--- a/bits.c
+++ b/bits.c
@@ -1,4 +1,3 @@
-#define DEBUG
/*
* Bitfield extraction functions. In each, start is a bit index (not a byte
* index) and width is a bit width (bounded above by the bit width of long
@@ -16,13 +15,15 @@
#endif /* DEBUG */
+
#define BITS_PER_BYTE 8
unsigned long long ubits(char buf[], unsigned int start, unsigned int width)
/* extract a bitfield from the buffer as an unsigned big-endian long */
{
unsigned long long fld = 0;
- unsigned int i;;
+ unsigned int i;
+ unsigned end;
assert(width <= sizeof(long long) * BITS_PER_BYTE);
for (i = start / BITS_PER_BYTE; i < (start + width + BITS_PER_BYTE - 1) / BITS_PER_BYTE; i++) {
@@ -33,12 +34,14 @@ unsigned long long ubits(char buf[], unsigned int start, unsigned int width)
printf("Extracting %d:%d from %s: segment 0x%llx = %lld\n", start, width, gpsd_hexdump(buf, 12), fld, fld);
#endif /* DEBUG */
- fld >>= (BITS_PER_BYTE - ((start + width) % BITS_PER_BYTE));
+ end = (start + width) % BITS_PER_BYTE;
+ if (end != 0) {
+ fld >>= (BITS_PER_BYTE - end);
#ifdef DEBUG
- printf("After downshifting by %d bits: 0x%llx = %lld\n",
- (BITS_PER_BYTE - ((start + width) % BITS_PER_BYTE)),
- fld, fld);
+ printf("After downshifting by %d bits: 0x%llx = %lld\n",
+ BITS_PER_BYTE - end, fld, fld);
#endif /* DEBUG */
+ }
fld &= ~(0xffffffff << width);
#ifdef DEBUG