|
|
@@ -0,0 +1,62 @@ |
|
|
|
class BitFieldMetaClass: |
|
|
|
def __init__(self, name, bases, dct): |
|
|
|
for base in bases: |
|
|
|
if base.__class__ is not BitFieldMetaClass: |
|
|
|
raise TypeError('BitField base class must be bit field') |
|
|
|
bases = filter(lambda x: x is not BitField, bases) |
|
|
|
self.__name__ = name |
|
|
|
self.__bases__ = bases |
|
|
|
d = self.__dict = {} |
|
|
|
for key, value in dct.items(): |
|
|
|
if key[:2] == '__': |
|
|
|
continue |
|
|
|
assert isinstance(value, int) |
|
|
|
d[key] = value |
|
|
|
|
|
|
|
def __call__(self, val): |
|
|
|
return BitFieldInstance(self.__name__, self.__dict, val) |
|
|
|
|
|
|
|
class BitFieldInstance(object): |
|
|
|
def __init__(self, name, d, v): |
|
|
|
self.__bfname = name |
|
|
|
self.__dict = d |
|
|
|
self.__value = v |
|
|
|
|
|
|
|
name = property(lambda x: x.__bfname) |
|
|
|
|
|
|
|
def __int__(self): |
|
|
|
return self.__value |
|
|
|
|
|
|
|
def __getattr__(self, k): |
|
|
|
if k[:19] == '_BitFieldInstance__': |
|
|
|
return object.__getattr__(self, k) |
|
|
|
|
|
|
|
try: |
|
|
|
return bool(self.__value & 1 << (self.__dict[k])) |
|
|
|
except KeyError: |
|
|
|
raise AttributeError('no field named: %s' % repr(k)) |
|
|
|
|
|
|
|
def __setattr__(self, k, v): |
|
|
|
if k[:19] == '_BitFieldInstance__': |
|
|
|
return object.__setattr__(self, k, v) |
|
|
|
|
|
|
|
bit = self.__dict[k] |
|
|
|
self.__value &= ~(1 << bit) |
|
|
|
self.__value |= bool(v) << bit |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
return '<%s>' % ','.join([ k for k in self.__dict if getattr(self, k) ]) |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
return 'BitFieldInstance(%s, %s, %s)' % (repr(self.__bfname), repr(self.__dict), repr(self.__value)) |
|
|
|
|
|
|
|
BitField = BitFieldMetaClass("BitField", (), {}) |
|
|
|
__all__ = [ 'BitField' ] |
|
|
|
|
|
|
|
def bftest(): |
|
|
|
class foo(BitField): |
|
|
|
bar = 3 |
|
|
|
foo = 4 |
|
|
|
bleh = 16 |
|
|
|
|
|
|
|
return foo(16) |