9 '''Decode binary data from a file'''
11 def __init__(self
, f
, b
='='):
12 '''Initialize with an open binary file and optional byte order'''
18 def set_byte_order(self
, b
):
19 '''Set the byte order, valid values are "big", "little", "swap", "native", "<", ">", "@", "="'''
25 # swap what ever the current byte order is
26 self
.byte_order
= swap_unpack_char()
29 elif b
== '<' or b
== '>' or b
== '@' or b
== '=':
32 print("error: invalid byte order specified: '%s'" % b
)
34 def is_in_memory(self
):
37 def seek(self
, offset
, whence
=0):
39 return self
.file.seek(offset
, whence
)
44 return self
.file.tell()
47 def read_size(self
, byte_size
):
48 s
= self
.file.read(byte_size
)
49 if len(s
) != byte_size
:
53 def push_offset_and_seek(self
, offset
):
54 '''Push the current file offset and seek to "offset"'''
55 self
.offsets
.append(self
.file.tell())
56 self
.file.seek(offset
, 0)
58 def pop_offset_and_seek(self
):
59 '''Pop a previously pushed file offset, or do nothing if there were no previously pushed offsets'''
60 if len(self
.offsets
) > 0:
61 self
.file.seek(self
.offsets
.pop())
63 def get_sint8(self
, fail_value
=0):
64 '''Extract a single int8_t from the binary file at the current file position, returns a single integer'''
67 v
, = struct
.unpack(self
.byte_order
+ 'b', s
)
72 def get_uint8(self
, fail_value
=0):
73 '''Extract a single uint8_t from the binary file at the current file position, returns a single integer'''
76 v
, = struct
.unpack(self
.byte_order
+ 'B', s
)
81 def get_sint16(self
, fail_value
=0):
82 '''Extract a single int16_t from the binary file at the current file position, returns a single integer'''
85 v
, = struct
.unpack(self
.byte_order
+ 'h', s
)
90 def get_uint16(self
, fail_value
=0):
91 '''Extract a single uint16_t from the binary file at the current file position, returns a single integer'''
94 v
, = struct
.unpack(self
.byte_order
+ 'H', s
)
99 def get_sint32(self
, fail_value
=0):
100 '''Extract a single int32_t from the binary file at the current file position, returns a single integer'''
101 s
= self
.read_size(4)
103 v
, = struct
.unpack(self
.byte_order
+ 'i', s
)
108 def get_uint32(self
, fail_value
=0):
109 '''Extract a single uint32_t from the binary file at the current file position, returns a single integer'''
110 s
= self
.read_size(4)
112 v
, = struct
.unpack(self
.byte_order
+ 'I', s
)
117 def get_sint64(self
, fail_value
=0):
118 '''Extract a single int64_t from the binary file at the current file position, returns a single integer'''
119 s
= self
.read_size(8)
121 v
, = struct
.unpack(self
.byte_order
+ 'q', s
)
126 def get_uint64(self
, fail_value
=0):
127 '''Extract a single uint64_t from the binary file at the current file position, returns a single integer'''
128 s
= self
.read_size(8)
130 v
, = struct
.unpack(self
.byte_order
+ 'Q', s
)
135 def get_fixed_length_c_string(
139 isprint_only_with_space_padding
=False):
140 '''Extract a single fixed length C string from the binary file at the current file position, returns a single C string'''
141 s
= self
.read_size(n
)
143 cstr
, = struct
.unpack(self
.byte_order
+ ("%i" % n
) + 's', s
)
144 # Strip trialing NULLs
145 cstr
= string
.strip(cstr
, "\0")
146 if isprint_only_with_space_padding
:
148 if c
in string
.printable
or ord(c
) == 0:
155 def get_c_string(self
):
156 '''Extract a single NULL terminated C string from the binary file at the current file position, returns a single C string'''
158 byte
= self
.get_uint8()
161 byte
= self
.get_uint8()
164 def get_n_sint8(self
, n
, fail_value
=0):
165 '''Extract "n" int8_t integers from the binary file at the current file position, returns a list of integers'''
166 s
= self
.read_size(n
)
168 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'b', s
)
170 return (fail_value
,) * n
172 def get_n_uint8(self
, n
, fail_value
=0):
173 '''Extract "n" uint8_t integers from the binary file at the current file position, returns a list of integers'''
174 s
= self
.read_size(n
)
176 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'B', s
)
178 return (fail_value
,) * n
180 def get_n_sint16(self
, n
, fail_value
=0):
181 '''Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers'''
182 s
= self
.read_size(2 * n
)
184 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'h', s
)
186 return (fail_value
,) * n
188 def get_n_uint16(self
, n
, fail_value
=0):
189 '''Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers'''
190 s
= self
.read_size(2 * n
)
192 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'H', s
)
194 return (fail_value
,) * n
196 def get_n_sint32(self
, n
, fail_value
=0):
197 '''Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers'''
198 s
= self
.read_size(4 * n
)
200 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'i', s
)
202 return (fail_value
,) * n
204 def get_n_uint32(self
, n
, fail_value
=0):
205 '''Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers'''
206 s
= self
.read_size(4 * n
)
208 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'I', s
)
210 return (fail_value
,) * n
212 def get_n_sint64(self
, n
, fail_value
=0):
213 '''Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers'''
214 s
= self
.read_size(8 * n
)
216 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'q', s
)
218 return (fail_value
,) * n
220 def get_n_uint64(self
, n
, fail_value
=0):
221 '''Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers'''
222 s
= self
.read_size(8 * n
)
224 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + 'Q', s
)
226 return (fail_value
,) * n