forked from itu-algorithms/itu.algs4
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinary_stdout.py
133 lines (113 loc) · 3.79 KB
/
binary_stdout.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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Created for BADS 2018
# See README.md for details
# This is python3
import struct
import sys
"""
Binary standard output. This class provides methods for converting
some primitive type variables (boolean, byte, char, and int)
to sequences of bits and writing them
to an output stream.
The output stream can be standard output or another outputstream.
Uses big-endian (most-significant byte first).
The client must flush() the output stream when finished writing bits.
The client should not intermix calls to BinaryOut with calls to stdout;
otherwise unexpected behavior will result.
"""
class BinaryStdOut:
out = sys.stdout.buffer
buffer_ = 0
n = 0
is_init = False
@staticmethod
def _initialize():
BinaryStdOut.buffer_ = 0 # 8-bit buffer of bits to write out
BinaryStdOut.n = 0 # number of bits used in buffer
BinaryStdOut.is_init = True
@staticmethod
def _write_bit(x):
if not BinaryStdOut.is_init:
BinaryStdOut._initialize()
BinaryStdOut.buffer_ <<= 1
if x:
BinaryStdOut.buffer_ |= 1
BinaryStdOut.n += 1
if BinaryStdOut.n == 8:
BinaryStdOut._clear_buffer()
@staticmethod
def _write_byte(x):
if not BinaryStdOut.is_init:
BinaryStdOut._initialize()
assert x >= 0 and x < 256
# optimized if byte-alligned
if BinaryStdOut.n == 0:
BinaryStdOut.out.write(struct.pack("B", x))
return
# otherwise write one bit at a time
for i in range(0, 8):
bit = ((x >> (8 - i - 1)) & 1) == 1
BinaryStdOut._write_bit(bit)
@staticmethod
def _clear_buffer():
if not BinaryStdOut.is_init:
BinaryStdOut._initialize()
if BinaryStdOut.n == 0:
return
if BinaryStdOut.n > 0:
BinaryStdOut.buffer_ <<= 8 - BinaryStdOut.n
BinaryStdOut.out.write(struct.pack("B", BinaryStdOut.buffer_))
BinaryStdOut.n = 0
BinaryStdOut.buffer_ = 0
@staticmethod
def flush():
BinaryStdOut._clear_buffer()
BinaryStdOut.out.flush()
@staticmethod
def close():
BinaryStdOut.flush()
BinaryStdOut.out.close()
BinaryStdOut.is_init = False
@staticmethod
def write_bool(x):
BinaryStdOut._write_bit(x)
@staticmethod
def write_byte(x):
BinaryStdOut._write_byte(x & 0xFF)
@staticmethod
def write_int(x, r=32):
if r == 32:
BinaryStdOut._write_byte(((x >> 24) & 0xFF))
BinaryStdOut._write_byte(((x >> 16) & 0xFF))
BinaryStdOut._write_byte(((x >> 8) & 0xFF))
BinaryStdOut._write_byte(((x >> 0) & 0xFF))
return
if r < 1 or r > 16:
raise ValueError("Illegal value for r = {}".format(r))
if x < 0 or x >= (1 << r):
raise ValueError("Illegal {}-bit char = {}".format(r, x))
for i in range(0, r):
bit = ((x >> (r - i - 1)) & 1) == 1
BinaryStdOut._write_bit(bit)
@staticmethod
def write_char(x, r=8):
if r == 8:
if ord(x) < 0 or ord(x) >= 256:
raise ValueError("Illegal 8-bit char = {}".format(x))
BinaryStdOut._write_byte(ord(x))
return
if r < 1 or r > 16:
raise ValueError("Illegal value for r = {}".format(r))
if ord(x) >= (1 << r):
raise ValueError("Illegal {}-bit char = {}".format(r, x))
for i in range(0, r):
bit = ((x >> (r - i - 1)) & 1) == 1
BinaryStdOut._write_bit(bit)
def write_string(s, r=8):
for i in s:
BinaryStdOut.write_char(i, r)
def main():
for i in sys.argv[1]:
BinaryStdOut.write_char(i)
BinaryStdOut.close()
if __name__ == "__main__":
main()