#!/usr/bin/python3
# ==============================================================
# hex dump
# ==============================================================
# --------------------------------------------------------------
# ---- display a chunk of bytes in hex and ASCII
# ----
# ---- byte array chunk should 16 bytes or less
# ----
# ---- byte array is a slice of the original array
# ---- starting at the start index
# --------------------------------------------------------------
def print_chunk(byt_ary,start_index):
ln = len(byt_ary)
print(f'{start_index:08} ',end='')
for i in range(16):
if i < ln:
byt = byt_ary[i]
print(f'{byt:02x} ',end='')
else:
print(' ',end='')
for i in range(16):
if i < ln:
byt = byt_ary[i]
if byt < 32 or byt > 126: # printable ASCII char?
bchr = '.'
else:
bchr = chr(byt)
else:
bchr = ' '
print(bchr,end='')
print()
# --------------------------------------------------------------
# ---- print title
# --------------------------------------------------------------
def print_hex_dump_title():
title = '-offset- ' +\
'--------------------- hex ---------------------' +\
' ---- ascii -----'
print(title)
# --------------------------------------------------------------
# ---- hex_dump start index and length
# ----
# ---- byt_ary byte array to hex dump
# ---- start starting offset (index) to display
# ---- length number of bytes to display
# --------------------------------------------------------------
def hex_dump_length(byt_ary,start,length):
if start < 0: return False
if length < 1: return False
end = start + length - 1
if end < start: return False
return hex_dump(byt_ary,start,end)
# --------------------------------------------------------------
# ---- hex_dump start/end index (inclusive)
# ----
# ---- byt_ary byte array to hex dump
# ---- start starting offset (index) to display
# ---- end ending offset (index) to display
# --------------------------------------------------------------
def hex_dump(byt_ary,start,end):
byt_ary_len =len(byt_ary)
# --- validate start,end array indexes
if start > byt_ary_len - 1:
start = byt_ary_len - 1
if end > byt_ary_len - 1:
end = byt_ary_len - 1
if end < start:
print(f'error: end < start {end} < {start}')
return False
# --- display hex dump chunks (16 bytes or less)
print_hex_dump_title()
while start <= end:
print_chunk(byt_ary[start:end+1],start)
start += 16
return True
# --------------------------------------------------------------
# ---- main
# --------------------------------------------------------------
if __name__ == '__main__':
import user_interface as ui
jpeg_file_path = 'mona_lisa_small_a.jpg'
with open(jpeg_file_path,'rb') as file:
jpeg_bytes = file.read()
def test_start_end():
print()
print(f'bytearray length = {len(jpeg_bytes)}')
while True:
# ---- test start/index
print()
s = ui.get_user_input('Enter start index: ')
if not s: break
tf,start = ui.is_integer(s)
if tf is not True or start < 0:
print(f'bad start index {s}')
continue
# ---- end index
print()
s = ui.get_user_input('Enter end index: ')
if not s: break
tf,end = ui.is_integer(s)
if tf is not True or end < start:
print(f'bad end index {s}')
continue
print()
tf = hex_dump(jpeg_bytes,start,end)
if tf is not True:
print('OOPS!')
def test_start_length():
print()
print(f'bytearray length = {len(jpeg_bytes)}')
while True:
# ---- test start/length
print()
s = ui.get_user_input('Enter start index: ')
if not s: break
tf,start = ui.is_integer(s)
if tf is not True or start < 0:
print(f'bad start index {s}')
continue
# ---- length
print()
s = ui.get_user_input('Enter length: ')
if not s: break
tf,length = ui.is_integer(s)
if tf is not True or length < 1:
print(f'bad length {s}')
continue
print()
tf = hex_dump_length(jpeg_bytes,start,length)
if tf is not True:
print('OOPS!')
# ---- which test
print()
s = ui.get_user_input('Test end or length [end,len]: ')
if not s: exit()
if s[0] =='l' or s[0] == 'L':
test_start_length()
elif s[0] == 'e' or s[0] == 'E':
test_start_end()
else:
print()
print('bad_selection')