Skip to content

Instantly share code, notes, and snippets.

@cheshirekow
Created May 31, 2018 21:28
Show Gist options
  • Save cheshirekow/e4cc3206014f4080288b4ff33356ea4e to your computer and use it in GitHub Desktop.
Save cheshirekow/e4cc3206014f4080288b4ff33356ea4e to your computer and use it in GitHub Desktop.
Simple BitField in python
class BitMember(object):
def __init__(self, size, offset=0):
self.size = size
self.offset = offset
@property
def mask(self):
return ~((~0) << (self.offset + self.size)) & ((~0) << self.offset)
class BitField(object):
def __init__(self):
self.value = 0
self._offset = 0
def __setattr__(self, name, value):
__dict__ = super(BitField, self).__getattribute__('__dict__')
obj = __dict__.get(name, None)
if isinstance(obj, BitMember):
offset = self.__dict__[name].offset
mask = self.__dict__[name].mask
# Clear the current value
self.value = self.value & ~mask
# Update with the new value
self.value |= (value << offset) & mask
else:
if isinstance(value, BitMember):
value = BitMember(value.size, offset=self._offset)
self._offset += value.size
super(BitField, self).__setattr__(name, value)
def __getattribute__(self, name):
__dict__ = super(BitField, self).__getattribute__('__dict__')
obj = __dict__.get(name, None)
if isinstance(obj, BitMember):
offset = self.__dict__[name].offset
mask = self.__dict__[name].mask
return (self.value & mask) >> offset
return super(BitField, self).__getattribute__(name)
def describe(self):
"""
Return a string describing the BitField. For example:
```
class MyVec(BitVector):
def __init__(self):
super(MyVec, self).__init__()
self.x = BitMember(0,3)
self.y = BitMember(3,1)
self.z = BitMember(4,10)
```
```
print MyVec().describe()
```
```
0000000000 0 000
c b a
off size field
--- ---- -----
a: 0 3 x
b: 3 1 y
c: 4 10 z
```
"""
__dict__ = super(BitField, self).__getattribute__('__dict__')
fields = []
for name, obj in __dict__.items():
if isinstance(obj, BitMember):
fields.append((obj.offset, name, obj))
fields = sorted(fields, reverse=True)
line0 = []
line1 = []
legend = []
keys = 'abcdefghijklmnopqrstuvwxyz'
for idx, (_, name, obj) in enumerate(fields):
key = keys[len(fields) - idx - 1]
line0.append('0' * obj.size)
line1.append('{}{}'.format(' ' * (obj.size - 1), key))
legend.append((key, obj, name))
out = io.StringIO()
out.write(u' '.join(line0))
out.write(u'\n')
out.write(u' '.join(line1))
out.write(u'\n\n')
out.write(u' off size field\n')
out.write(u' --- ---- -----\n')
for key, obj, name in legend[::-1]:
out.write(u'{:1s}: {:3d} {:4d} {}\n'.format(
key, obj.offset, obj.size, name))
return out.getvalue()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment