Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract bitfields from an int in Python

I have a number like 0x5423 where I want to extract 4 values:

a = 0x5   # 15 downto 12
b = 0x42  # 11 downto 3
c = 0x3   # 3 downto 2
d = 0x00  # 1 downto 0

I discovered the module bitstrings that looks great. Unfortunately, for an unknown reason, the bits are numbered from the right.

This is bad because if a add some upper bits like 0xA5423 my extraction won't work anymore:

field = bitstrings.BitArray('0x5423')
a = field[0:4].uint
b = field[4:12].uint
c = field[12:14].uint
d = field[14:16].uint

How can I properly extract my bitfields without complex arithmetic manipulations such as:

b = (a >> 4) & 0xFF

Ideally I would have:

b = field.range(11, 4)
like image 697
nowox Avatar asked Oct 31 '22 13:10

nowox


1 Answers

Convert the string to 0x#### format before pass to bitstring.BitArray:

>>> n = '0xA5423'
>>> n = '0x{:04x}'.format(int(n, 16) & 0xffff)  # => '0x5423'
>>> field = bitstring.BitArray(n)
>>> field[0:4].uint
5
>>> field[4:12].uint  # 0x42 == 66
66
>>> field[12:14].uint
0
>>> field[14:16].uint
3

UPDATE another solution that does not depend on bitstring, and count from left(according to OP):

Convert the number into binary format:

>>> n = '0xA5423'
>>> n = format(int(n, 16), '016b')[::-1]  # reversed
>>> n
'11000100001010100101'
>>> int(n[0:2][::-1], 2)  # need to reverse again to get proper value
3
>>> int(n[2:4][::-1], 2)
0
>>> int(n[4:12][::-1], 2)
66
>>> int(n[12:16][::-1], 2)
5
like image 57
falsetru Avatar answered Nov 08 '22 10:11

falsetru