Blame | Last modification | View Log | Download
# Written by Bram Cohen, Uoti Urpala, and John Hoffman# see LICENSE.txt for license informationtry:Trueexcept:True = 1False = 0bool = lambda x: not not xtry:sum([1])negsum = lambda a: len(a)-sum(a)except:negsum = lambda a: reduce(lambda x,y: x+(not y), a, 0)def _int_to_booleans(x):r = []for i in range(8):r.append(bool(x & 0x80))x <<= 1return tuple(r)lookup_table = []reverse_lookup_table = {}for i in xrange(256):x = _int_to_booleans(i)lookup_table.append(x)reverse_lookup_table[x] = chr(i)class Bitfield:def __init__(self, length = None, bitstring = None, copyfrom = None):if copyfrom is not None:self.length = copyfrom.lengthself.array = copyfrom.array[:]self.numfalse = copyfrom.numfalsereturnif length is None:raise ValueError, "length must be provided unless copying from another array"self.length = lengthif bitstring is not None:extra = len(bitstring) * 8 - lengthif extra < 0 or extra >= 8:raise ValueErrort = lookup_tabler = []for c in bitstring:r.extend(t[ord(c)])if extra > 0:if r[-extra:] != [0] * extra:raise ValueErrordel r[-extra:]self.array = rself.numfalse = negsum(r)else:self.array = [False] * lengthself.numfalse = lengthdef __setitem__(self, index, val):val = bool(val)self.numfalse += self.array[index]-valself.array[index] = valdef __getitem__(self, index):return self.array[index]def __len__(self):return self.lengthdef tostring(self):booleans = self.arrayt = reverse_lookup_tables = len(booleans) % 8r = [ t[tuple(booleans[x:x+8])] for x in xrange(0, len(booleans)-s, 8) ]if s:r += t[tuple(booleans[-s:] + ([0] * (8-s)))]return ''.join(r)def complete(self):return not self.numfalsedef test_bitfield():try:x = Bitfield(7, 'ab')assert Falseexcept ValueError:passtry:x = Bitfield(7, 'ab')assert Falseexcept ValueError:passtry:x = Bitfield(9, 'abc')assert Falseexcept ValueError:passtry:x = Bitfield(0, 'a')assert Falseexcept ValueError:passtry:x = Bitfield(1, '')assert Falseexcept ValueError:passtry:x = Bitfield(7, '')assert Falseexcept ValueError:passtry:x = Bitfield(8, '')assert Falseexcept ValueError:passtry:x = Bitfield(9, 'a')assert Falseexcept ValueError:passtry:x = Bitfield(7, chr(1))assert Falseexcept ValueError:passtry:x = Bitfield(9, chr(0) + chr(0x40))assert Falseexcept ValueError:passassert Bitfield(0, '').tostring() == ''assert Bitfield(1, chr(0x80)).tostring() == chr(0x80)assert Bitfield(7, chr(0x02)).tostring() == chr(0x02)assert Bitfield(8, chr(0xFF)).tostring() == chr(0xFF)assert Bitfield(9, chr(0) + chr(0x80)).tostring() == chr(0) + chr(0x80)x = Bitfield(1)assert x.numfalse == 1x[0] = 1assert x.numfalse == 0x[0] = 1assert x.numfalse == 0assert x.tostring() == chr(0x80)x = Bitfield(7)assert len(x) == 7x[6] = 1assert x.numfalse == 6assert x.tostring() == chr(0x02)x = Bitfield(8)x[7] = 1assert x.tostring() == chr(1)x = Bitfield(9)x[8] = 1assert x.numfalse == 8assert x.tostring() == chr(0) + chr(0x80)x = Bitfield(8, chr(0xC4))assert len(x) == 8assert x.numfalse == 5assert x.tostring() == chr(0xC4)