1 /* bits.c - bitfield extraction code
3 * This file is Copyright (c)2010 by the GPSD project
4 * BSD terms apply: see the file COPYING in the distribution root for details.
6 * Bitfield extraction functions. In each, start is a bit index (not
7 * a byte index) and width is a bit width. The width bounded above by
8 * the bit width of a long long, which is 64 bits in all standard data
9 * models for 32- and 64-bit processors.
11 * The sbits() function assumes twos-complement arithmetic.
21 #define BITS_PER_BYTE 8
23 unsigned long long ubits(char buf[], unsigned int start, unsigned int width)
24 /* extract a (zero-origin) bitfield from the buffer as an unsigned big-endian long long */
26 unsigned long long fld = 0;
30 /*@i1@*/ assert(width <= sizeof(long long) * BITS_PER_BYTE);
31 for (i = start / BITS_PER_BYTE;
32 i < (start + width + BITS_PER_BYTE - 1) / BITS_PER_BYTE; i++) {
33 fld <<= BITS_PER_BYTE;
34 fld |= (unsigned char)buf[i];
37 (void)printf("%d:%d from %s:\n", start, width, gpsd_hexdump(buf, 32));
41 (void)printf(" segment=0x%llx,", fld);
43 end = (start + width) % BITS_PER_BYTE;
45 fld >>= (BITS_PER_BYTE - end);
47 (void)printf(" after downshifting by %d bits: 0x%llx",
48 BITS_PER_BYTE - end, fld);
52 (void)printf(" = %lld\n", fld);
55 /*@ -shiftimplementation @*/
56 fld &= ~(-1LL << width);
57 /*@ +shiftimplementation @*/
60 printf(" after selecting out the bottom %u bits: 0x%llx = %lld\n",
67 signed long long sbits(char buf[], unsigned int start, unsigned int width)
68 /* extract a bitfield from the buffer as a signed big-endian long */
70 unsigned long long fld = ubits(buf, start, width);
73 (void)fprintf(stderr, "sbits(%d, %d) extracts %llx\n", start, width, fld);
76 if (fld & (1 << (width - 1))) {
78 (void)fprintf(stderr, "%llx is signed\n", fld);
80 /*@ -shiftimplementation @*/
81 fld |= (-1LL << (width - 1));
82 /*@ +shiftimplementation @*/
85 (void)fprintf(stderr, "sbits(%d, %d) returns %lld\n", start, width,
86 (signed long long)fld);
88 return (signed long long)fld;