1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
/* bits.c - bitfield extraction code
*
* This file is Copyright (c)2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
*
* Bitfield extraction functions. In each, start is a bit index - not
* a byte index - and width is a bit width. The width is bounded above by
* 64 bits.
*
* The sbits() function assumes twos-complement arithmetic. ubits()
* and sbits() assume no padding in integers.
*/
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include "bits.h"
uint64_t ubits(char buf[], unsigned int start, unsigned int width, bool le)
/* extract a (zero-origin) bitfield from the buffer as an unsigned big-endian uint64_t */
{
uint64_t fld = 0;
unsigned int i;
unsigned end;
/*@i1@*/ assert(width <= sizeof(uint64_t) * CHAR_BIT);
for (i = start / CHAR_BIT;
i < (start + width + CHAR_BIT - 1) / CHAR_BIT; i++) {
/*@i1@*/fld <<= CHAR_BIT;
fld |= (unsigned char)buf[i];
}
end = (start + width) % CHAR_BIT;
if (end != 0) {
/*@i1@*/fld >>= (CHAR_BIT - end);
}
/*@ -shiftimplementation @*/
fld &= ~(-1LL << width);
/*@ +shiftimplementation @*/
/* was extraction as a little-endian requested? */
if (le)
{
uint64_t reversed = 0;
for (i = width; i; --i)
{
reversed <<= 1;
if (fld & 1)
reversed |= 1;
fld >>= 1;
}
fld = reversed;
}
return fld;
}
int64_t sbits(char buf[], unsigned int start, unsigned int width, bool le)
/* extract a bitfield from the buffer as a signed big-endian long */
{
uint64_t fld = ubits(buf, start, width, le);
/*@ +relaxtypes */
if (fld & (1LL << (width - 1))) {
/*@ -shiftimplementation @*/
fld |= (-1LL << (width - 1));
/*@ +shiftimplementation @*/
}
return (int64_t)fld;
/*@ -relaxtypes */
}
#ifdef __UNUSED__
// cppcheck-suppress unusedFunction
u_int16_t swap_u16(u_int16_t i)
/* byte-swap a 16-bit unsigned int */
{
u_int8_t c1, c2;
c1 = i & 255;
c2 = (i >> 8) & 255;
return (c1 << 8) + c2;
}
// cppcheck-suppress unusedFunction
u_int32_t swap_u32(u_int32_t i)
/* byte-swap a 32-bit unsigned int */
{
u_int8_t c1, c2, c3, c4;
c1 = i & 255;
c2 = (i >> 8) & 255;
c3 = (i >> 16) & 255;
c4 = (i >> 24) & 255;
return ((u_int32_t)c1 << 24) + ((u_int32_t)c2 << 16) + ((u_int32_t)c3 << 8) + c4;
}
// cppcheck-suppress unusedFunction
u_int64_t swap_u64(u_int64_t i)
/* byte-swap a 64-bit unsigned int */
{
u_int8_t c1, c2, c3, c4, c5, c6, c7, c8;
c1 = i & 255;
c2 = (i >> 8) & 255;
c3 = (i >> 16) & 255;
c4 = (i >> 24) & 255;
c5 = (i >> 32) & 255;
c6 = (i >> 40) & 255;
c7 = (i >> 48) & 255;
c8 = (i >> 56) & 255;
return ((u_int64_t)c1 << 56) +
((u_int64_t)c2 << 48) +
((u_int64_t)c3 << 40) +
((u_int64_t)c4 << 32) +
((u_int64_t)c5 << 24) +
((u_int64_t)c6 << 16) +
((u_int64_t)c7 << 8) +
c8;
}
#endif /* __UNUSED__ */
|