-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitio.py
66 lines (54 loc) · 1.82 KB
/
bitio.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Adapted from http://rosettacode.org/wiki/Bitwise_IO#Python by Roshan
# Shariff. Licensed under the GNU Free Documentation License 1.2
class BitWriter:
def __init__(self, f):
'''f must be an output stream opened in binary mode.'''
self.accumulator = 0
self.bcount = 0
self.out = f
def __del__(self):
try:
self.flush()
except ValueError: # I/O operation on closed file
pass
def writebit(self, bit):
'''Writes 1 if 'bit' is true, 0 otherwise.'''
if self.bcount == 8:
self.flush()
if bit:
self.accumulator |= (1 << (7-self.bcount))
self.bcount += 1
def writebits(self, bits, n):
'''Writes 'n' least significant bits of integer 'bits'.'''
while n > 0:
self.writebit(bits & (1 << (n-1)))
n -= 1
def flush(self):
'''MUST CALL WHEN DONE. Writes out any partial bytes to file.'''
self.out.write(bytes((self.accumulator,)))
self.accumulator = 0
self.bcount = 0
class BitReader:
def __init__(self, f):
'''f must be an input stream opened in binary mode.'''
self.accumulator = 0
self.bcount = 0
self.input = f
def readbit(self):
'''Reads one bit and returns as 1 or 0.'''
if self.bcount == 0:
a = self.input.read(1)
if a:
self.accumulator = a[0]
self.bcount = 8
else:
raise EOFError('End of file while reading bits')
self.bcount -= 1
return (self.accumulator >> self.bcount) & 1
def readbits(self, n):
'''Reads n bits and returns them packed into an integer.'''
v = 0
while n > 0:
v = (v << 1) | self.readbit()
n -= 1
return v