/
binio.py
147 lines (105 loc) · 3.31 KB
/
binio.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import struct
import io
class BinIO(object):
def __init__(self, stream, endian='='):
self.stream = stream
self.endian = endian
def seek(self, offset, whence=io.SEEK_SET):
return self.stream.seek(offset, whence)
def tell(self):
return self.stream.tell()
## Read methods
def read(self, *args):
return self.stream.read(*args)
def skip(self, num):
self.seek(num, io.SEEK_CUR)
def align(self, num):
current_pos = self.stream.tell()
align_bytes = num - (current_pos % num)
if align_bytes != num:
self.stream.seek(align_bytes, io.SEEK_CUR)
def unpack(self, fmt):
fmt = self.endian + fmt
fmt_size = struct.calcsize(fmt)
return struct.unpack(fmt, self.stream.read(fmt_size))
def unpack_one(self, fmt):
values = self.unpack(fmt)
assert len(values) == 1
return values[0]
def read_char(self):
return self.unpack_one("c")
def read_int8(self):
return self.unpack_one("b")
def read_uint8(self):
return self.unpack_one("B")
def read_int16(self):
return self.unpack_one("h")
def read_uint16(self):
return self.unpack_one("H")
def read_int32(self):
return self.unpack_one("l")
def read_uint32(self):
return self.unpack_one("L")
def read_int64(self):
return self.unpack_one("q")
def read_uint64(self):
return self.unpack_one("Q")
def read_float(self):
return self.unpack_one("f")
def read_double(self):
return self.unpack_one("d")
def read_bool(self):
return self.unpack_one("?")
def read_char(self):
return self.unpack_one("c")
def read_cstring(self, charsize=1):
string = b""
while True:
c = self.read(charsize)
if int.from_bytes(c, "little") == 0:
break
else:
string += c
return string
# Write methods
def write(self, *args):
return self.stream.write(*args)
def pad(self, num):
self.write(b"\x00" * num)
def align_pad(self, num):
current_pos = self.stream.tell()
align_bytes = num - (current_pos % num)
if align_bytes != num:
self.pad(align_bytes)
def pack(self, fmt, *values):
fmt = self.endian + fmt
fmt_size = struct.calcsize(fmt)
return self.stream.write(struct.pack(fmt, *values))
def write_char(self, val):
self.pack("c", val)
def write_int8(self, val):
self.pack("b", val)
def write_uint8(self, val):
self.pack("B", val)
def write_int16(self, val):
self.pack("h", val)
def write_uint16(self, val):
self.pack("H", val)
def write_int32(self, val):
self.pack("l", val)
def write_uint32(self, val):
self.pack("L", val)
def write_int64(self, val):
self.pack("q", val)
def write_uint64(self, val):
self.pack("Q", val)
def write_float(self, val):
self.pack("f", val)
def write_double(self, val):
self.pack("d", val)
def write_bool(self, val):
self.pack("?", val)
def write_char(self, val):
self.pack("c", val)
def write_cstring(self, val):
self.write(val + b"\x00")