Add bitops2.getBitsBE
This commit is contained in:
parent
a99dafab42
commit
b9e847a143
|
@ -20,6 +20,9 @@
|
|||
|
||||
{.push raises: [].}
|
||||
|
||||
import
|
||||
endians2
|
||||
|
||||
const
|
||||
useBuiltins = not defined(noIntrinsicsBitOpts)
|
||||
|
||||
|
@ -595,3 +598,47 @@ template lowerBitLE*(bytes: var openarray[byte], pos: Natural) {.deprecated: "cl
|
|||
clearBitLE(bytes, pos)
|
||||
template lowerBitBE*(bytes: var openarray[byte], pos: Natural) {.deprecated: "clearBitBE".} =
|
||||
clearBitBE(bytes, pos)
|
||||
|
||||
func getBitsBE*(data: openarray[byte], slice: HSlice, T: type[SomeUnsignedInt]): T =
|
||||
## Treats `data` as an unsigned big endian integer and returns a slice of bits
|
||||
## extracted from it, assuming 0 to be the possition of the most significant bit.
|
||||
let totalBits = data.len * 8
|
||||
|
||||
template normalizeIdx(idx): int =
|
||||
when idx is BackwardsIndex: totalBits - int(idx)
|
||||
else: int(idx)
|
||||
|
||||
let
|
||||
a = normalizeIdx(slice.a)
|
||||
b = normalizeIdx(slice.b) + 1
|
||||
sliceLen = b - a
|
||||
|
||||
const resultBits = sizeof(result) * 8
|
||||
doAssert a < b and sliceLen <= resultBits and b <= totalBits
|
||||
|
||||
let limbs = cast[ptr UncheckedArray[T]](unsafeAddr data[0])
|
||||
|
||||
template readLimb(idx: int): auto =
|
||||
when cpuEndian == bigEndian or sizeof(result) == 1:
|
||||
limbs[][idx]
|
||||
else:
|
||||
swapBytes(limbs[][idx])
|
||||
|
||||
let
|
||||
firstLimbIdx = a div resultBits
|
||||
firstLimbUnusedBits = (a mod resultBits)
|
||||
firstLimbUsedBits = resultBits - firstLimbUnusedBits
|
||||
firstLimb = readLimb firstLimbIdx
|
||||
|
||||
if sliceLen > firstLimbUsedBits:
|
||||
let
|
||||
bitsFromSecondLimb = sliceLen - firstLimbUsedBits
|
||||
secondLimb = readLimb(firstLimbIdx + 1)
|
||||
((firstLimb shl firstLimbUnusedBits) shr (firstLimbUnusedBits - bitsFromSecondLimb)) or
|
||||
(secondLimb shr (resultBits - bitsFromSecondLimb))
|
||||
else:
|
||||
(firstLimb shl firstLimbUnusedBits) shr (resultBits - sliceLen)
|
||||
|
||||
template getBitsBE*(data: openarray[byte], slice: HSlice): BiggestUInt =
|
||||
getBitsBE(data, slice, BiggestUInt)
|
||||
|
||||
|
|
|
@ -86,8 +86,47 @@ template test() =
|
|||
# T(1 shl 63) raises!
|
||||
doAssert bit64 == 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000'u64
|
||||
|
||||
proc runtimeTest =
|
||||
var bytes = @[byte 0b11001101, 0b10010010, 0b00000000, 0b11111111,
|
||||
0b11000010, 0b00110110, 0b11010110, 0b00101010,
|
||||
0b01101110, 0b11101001, 0b10101011, 0b00110010]
|
||||
|
||||
doAssert getBitsBE(bytes, 0..0, byte) == byte(1)
|
||||
doAssert getBitsBE(bytes, 1..1, byte) == byte(1)
|
||||
doAssert getBitsBE(bytes, 2..2, byte) == byte(0)
|
||||
doAssert getBitsBE(bytes, 6..6, byte) == byte(0)
|
||||
doAssert getBitsBE(bytes, 7..7, byte) == byte(1)
|
||||
|
||||
doAssert getBitsBE(bytes, 0..1, byte) == byte(0b11)
|
||||
doAssert getBitsBE(bytes, 1..2, byte) == byte(0b10)
|
||||
doAssert getBitsBE(bytes, 2..3, byte) == byte(0)
|
||||
doAssert getBitsBE(bytes, 5..6, byte) == byte(0b10)
|
||||
doAssert getBitsBE(bytes, 6..7, byte) == byte(0b1)
|
||||
|
||||
doAssert getBitsBE(bytes, 7..8, byte) == byte(0b11)
|
||||
|
||||
doAssert getBitsBE(bytes, 0..2, byte) == byte(0b110)
|
||||
doAssert getBitsBE(bytes, 1..3, byte) == byte(0b100)
|
||||
doAssert getBitsBE(bytes, 6..9, byte) == byte(0b110)
|
||||
|
||||
doAssert getBitsBE(bytes, 0..3, byte) == byte(0b1100)
|
||||
doAssert getBitsBE(bytes, 0..7, byte) == byte(0b11001101)
|
||||
|
||||
doAssert getBitsBE(bytes, 0..10, uint16) == uint16(0b11001101100)
|
||||
doAssert getBitsBE(bytes, 0..15, uint16) == uint16(0b1100110110010010)
|
||||
doAssert getBitsBE(bytes, 1..11, uint16) == uint16(0b10011011001)
|
||||
doAssert getBitsBE(bytes, 3..18, uint16) == uint16(0b110110010010000)
|
||||
doAssert getBitsBE(bytes, 35..50, uint16) == uint16(0b1000110110110)
|
||||
|
||||
doAssert getBitsBE(bytes, 4..7, uint16) == uint16(0b1101)
|
||||
doAssert getBitsBE(bytes, 1..29) == 0b10011011001001000000000111111'u64
|
||||
doAssert getBitsBE(bytes, 1..25, uint32) == 0b1001101100100100000000011'u32
|
||||
doAssert getBitsBE(bytes, 1..25, uint32) == 0b1001101100100100000000011'u32
|
||||
|
||||
static: test()
|
||||
|
||||
suite "bitops2":
|
||||
test "bitops2_test":
|
||||
test() # Cannot use unittest at compile time..
|
||||
runtimeTest()
|
||||
|
||||
|
|
Loading…
Reference in New Issue