Skip to content

Commit

Permalink
as_hexdump() using aligned chunks.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Jan 31, 2018
1 parent 1c9b01c commit 264c1cb
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 33 deletions.
56 changes: 24 additions & 32 deletions bincopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,8 +933,7 @@ def as_array(self, minimum_address=None, padding=None, separator=', '):
initialization code for c and other languages.
:param minimum_address: Start address of the resulting binary
data. Must be less than or equal to
the start address of the binary data.
data.
:param padding: Value of the padding between not adjacent
segments.
Expand All @@ -961,22 +960,32 @@ def as_array(self, minimum_address=None, padding=None, separator=', '):
return separator.join(words)

def as_hexdump(self):
"""Format the binary file as a hexdump. This function can be used to
generate array.
"""Format the binary file as a hexdump.
:returns: A hexdump string.
"""

# Empty file?
if len(self) == 0:
return '\n'

non_dot_characters = set(string.printable)
non_dot_characters -= set(string.whitespace)
non_dot_characters |= set(' ')

def align16(address):
return address - (address % 16)

def padding(length):
return [None] * length

def format_line(address, data):
"""`data` is a list of integers and None for unused elements.
"""

data += padding(16 - len(data))
hexdata = []

for byte in data:
Expand All @@ -989,7 +998,6 @@ def format_line(address, data):

first_half = ' '.join(hexdata[0:8])
second_half = ' '.join(hexdata[8:16])

text = ''

for byte in data:
Expand All @@ -1003,43 +1011,27 @@ def format_line(address, data):
return '{:08x} {:23s} {:23s} |{:16s}|'.format(
address, first_half, second_half, text)

# Format one line at a time.
lines = []
line_address = None
line_address = align16(self.minimum_address)
line_data = []

for address, data in self._segments.chunks(16):
if line_address is None:
# A new line.
line_address = address - (address % 16)
line_data = []
elif address > line_address + 16:
line_data += [None] * (16 - len(line_data))
for chunk in self._segments.chunks(size=16, alignment=16):
aligned_chunk_address = align16(chunk.address)

if aligned_chunk_address > line_address:
lines.append(format_line(line_address, line_data))

if address > line_address + 32:
if aligned_chunk_address > line_address + 16:
lines.append('...')

line_address = address - (address % 16)
line_address = aligned_chunk_address
line_data = []

line_data += [None] * (address - (line_address + len(line_data)))
line_left = 16 - len(line_data)

if len(data) > line_left:
line_data += [byte for byte in data[0:line_left]]
lines.append(format_line(line_address, line_data))
line_address += 16
line_data = [byte for byte in data[line_left:]]
elif len(data) == line_left:
line_data += [byte for byte in data]
lines.append(format_line(line_address, line_data))
line_address = None
else:
line_data += [byte for byte in data]
line_data += padding(chunk.address - line_address - len(line_data))
line_data += [byte for byte in chunk.data]

if line_address is not None:
line_data += [None] * (16 - len(line_data))
lines.append(format_line(line_address, line_data))
lines.append(format_line(line_address, line_data))

return '\n'.join(lines) + '\n'

Expand Down
5 changes: 5 additions & 0 deletions tests/files/hexdump3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
00000000 31 |1 |
...
00000020 33 |3 |
...
00000050 36 |6 |
19 changes: 18 additions & 1 deletion tests/test_bincopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def test_array(self):
with open('tests/files/in.i') as fin:
self.assertEqual(binfile.as_array() + '\n', fin.read())

def test_hexdump(self):
def test_hexdump_1(self):
binfile = bincopy.BinFile()
binfile.add_binary(b'12',address=17)
binfile.add_binary(b'34', address=26)
Expand All @@ -402,6 +402,7 @@ def test_hexdump(self):
with open('tests/files/hexdump.txt') as fin:
self.assertEqual(binfile.as_hexdump(), fin.read())

def test_hexdump_2(self):
binfile = bincopy.BinFile()
binfile.add_binary(b'34', address=0x150)
binfile.add_binary(b'3', address=0x163)
Expand All @@ -411,6 +412,22 @@ def test_hexdump(self):
with open('tests/files/hexdump2.txt') as fin:
self.assertEqual(binfile.as_hexdump(), fin.read())

def test_hexdump_gaps(self):
binfile = bincopy.BinFile()
binfile.add_binary(b'1', address=0)
# One line gap as "...".
binfile.add_binary(b'3', address=32)
# Two lines gap as "...".
binfile.add_binary(b'6', address=80)

with open('tests/files/hexdump3.txt') as fin:
self.assertEqual(binfile.as_hexdump(), fin.read())

def test_hexdump_empty(self):
binfile = bincopy.BinFile()

self.assertEqual(binfile.as_hexdump(), '\n')

def test_srec_ihex_binary(self):
binfile = bincopy.BinFile()

Expand Down

0 comments on commit 264c1cb

Please sign in to comment.