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(
136 self
, n
, fail_value
="", isprint_only_with_space_padding
=False
138 """Extract a single fixed length C string from the binary file at the current file position, returns a single C string"""
139 s
= self
.read_size(n
)
141 (cstr
,) = struct
.unpack(self
.byte_order
+ ("%i" % n
) + "s", s
)
142 # Strip trialing NULLs
143 cstr
= string
.strip(cstr
, "\0")
144 if isprint_only_with_space_padding
:
146 if c
in string
.printable
or ord(c
) == 0:
153 def get_c_string(self
):
154 """Extract a single NULL terminated C string from the binary file at the current file position, returns a single C string"""
156 byte
= self
.get_uint8()
159 byte
= self
.get_uint8()
162 def get_n_sint8(self
, n
, fail_value
=0):
163 """Extract "n" int8_t integers from the binary file at the current file position, returns a list of integers"""
164 s
= self
.read_size(n
)
166 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "b", s
)
168 return (fail_value
,) * n
170 def get_n_uint8(self
, n
, fail_value
=0):
171 """Extract "n" uint8_t integers from the binary file at the current file position, returns a list of integers"""
172 s
= self
.read_size(n
)
174 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "B", s
)
176 return (fail_value
,) * n
178 def get_n_sint16(self
, n
, fail_value
=0):
179 """Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers"""
180 s
= self
.read_size(2 * n
)
182 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "h", s
)
184 return (fail_value
,) * n
186 def get_n_uint16(self
, n
, fail_value
=0):
187 """Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers"""
188 s
= self
.read_size(2 * n
)
190 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "H", s
)
192 return (fail_value
,) * n
194 def get_n_sint32(self
, n
, fail_value
=0):
195 """Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers"""
196 s
= self
.read_size(4 * n
)
198 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "i", s
)
200 return (fail_value
,) * n
202 def get_n_uint32(self
, n
, fail_value
=0):
203 """Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers"""
204 s
= self
.read_size(4 * n
)
206 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "I", s
)
208 return (fail_value
,) * n
210 def get_n_sint64(self
, n
, fail_value
=0):
211 """Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers"""
212 s
= self
.read_size(8 * n
)
214 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "q", s
)
216 return (fail_value
,) * n
218 def get_n_uint64(self
, n
, fail_value
=0):
219 """Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers"""
220 s
= self
.read_size(8 * n
)
222 return struct
.unpack(self
.byte_order
+ ("%u" % n
) + "Q", s
)
224 return (fail_value
,) * n