Add bitops2.getBitsBE
This commit is contained in:
parent
a99dafab42
commit
b9e847a143
|
@ -20,6 +20,9 @@
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
endians2
|
||||||
|
|
||||||
const
|
const
|
||||||
useBuiltins = not defined(noIntrinsicsBitOpts)
|
useBuiltins = not defined(noIntrinsicsBitOpts)
|
||||||
|
|
||||||
|
@ -595,3 +598,47 @@ template lowerBitLE*(bytes: var openarray[byte], pos: Natural) {.deprecated: "cl
|
||||||
clearBitLE(bytes, pos)
|
clearBitLE(bytes, pos)
|
||||||
template lowerBitBE*(bytes: var openarray[byte], pos: Natural) {.deprecated: "clearBitBE".} =
|
template lowerBitBE*(bytes: var openarray[byte], pos: Natural) {.deprecated: "clearBitBE".} =
|
||||||
clearBitBE(bytes, pos)
|
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!
|
# T(1 shl 63) raises!
|
||||||
doAssert bit64 == 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000'u64
|
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()
|
static: test()
|
||||||
|
|
||||||
suite "bitops2":
|
suite "bitops2":
|
||||||
test "bitops2_test":
|
test "bitops2_test":
|
||||||
test() # Cannot use unittest at compile time..
|
test() # Cannot use unittest at compile time..
|
||||||
|
runtimeTest()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue