You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
4.2 KiB
119 lines
4.2 KiB
#!/usr/bin/env python3 |
|
# |
|
# Copyright (c) 2017 Intel Corporation |
|
# Copyright (c) 2025 Siemens AG |
|
# |
|
# SPDX-License-Identifier: Apache-2.0 |
|
|
|
|
|
"""Convert a file to a list of hex characters |
|
|
|
The list of hex characters can then be included to a source file. Optionally, |
|
the output can be compressed. |
|
|
|
""" |
|
|
|
import argparse |
|
import codecs |
|
import gzip |
|
import io |
|
|
|
|
|
def parse_args(): |
|
global args |
|
|
|
parser = argparse.ArgumentParser( |
|
description=__doc__, |
|
formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) |
|
|
|
parser.add_argument("-f", "--file", required=True, help="Input file") |
|
parser.add_argument("-o", "--offset", type=lambda x: int(x, 0), default=0, |
|
help="Byte offset in the input file") |
|
parser.add_argument("-l", "--length", type=lambda x: int(x, 0), default=-1, |
|
help="""Length in bytes to read from the input file. |
|
Defaults to reading till the end of the input file.""") |
|
parser.add_argument("-m", "--format", default="list", |
|
help="Output format: 'list' (default) or 'literal' (string literal)") |
|
parser.add_argument("-g", "--gzip", action="store_true", |
|
help="Compress the file using gzip before output") |
|
parser.add_argument("-t", "--gzip-mtime", type=int, default=0, |
|
nargs='?', const=None, |
|
help="""mtime seconds in the gzip header. |
|
Defaults to zero to keep builds deterministic. For |
|
current date and time (= "now") use this option |
|
without any value.""") |
|
args = parser.parse_args() |
|
|
|
|
|
def get_nice_string(list_or_iterator): |
|
# Convert into comma separated list form. |
|
s = ", ".join("0x" + str(x) for x in list_or_iterator) |
|
|
|
# Format the list to eight values per line. |
|
return "\n".join(s[i:i+47] for i in range(0, len(s), 48)) |
|
|
|
|
|
def make_hex(chunk): |
|
hexdata = codecs.encode(chunk, 'hex').decode("utf-8") |
|
hexlist = map(''.join, zip(*[iter(hexdata)] * 2)) |
|
print(get_nice_string(hexlist) + ',') |
|
|
|
|
|
def make_string_literal(chunk): |
|
hexdata = codecs.encode(chunk, 'hex').decode("utf-8") |
|
hexlist = map(''.join, zip(*[iter(hexdata)] * 2)) |
|
print(''.join("\\x" + str(x) for x in hexlist), end='') |
|
|
|
|
|
def main(): |
|
parse_args() |
|
|
|
if args.gzip: |
|
with io.BytesIO() as content: |
|
with open(args.file, 'rb') as fg: |
|
fg.seek(args.offset) |
|
with gzip.GzipFile(fileobj=content, mode='w', |
|
mtime=args.gzip_mtime, |
|
compresslevel=9) as gz_obj: |
|
gz_obj.write(fg.read(args.length)) |
|
|
|
content.seek(0) |
|
if args.format == "literal": |
|
print('"', end='') |
|
for chunk in iter(lambda: content.read(1024), b''): |
|
make_string_literal(chunk) |
|
print('"', end='') |
|
else: |
|
for chunk in iter(lambda: content.read(1024), b''): |
|
make_hex(chunk) |
|
else: |
|
with open(args.file, "rb") as fp: |
|
fp.seek(args.offset) |
|
|
|
if args.format == "literal": |
|
if args.length < 0: |
|
print('"', end='') |
|
for chunk in iter(lambda: fp.read(1024), b''): |
|
make_string_literal(chunk) |
|
print('"', end='') |
|
else: |
|
print('"', end='') |
|
remainder = args.length |
|
for chunk in iter(lambda: fp.read(min(1024, remainder)), b''): |
|
make_string_literal(chunk) |
|
remainder = remainder - len(chunk) |
|
print('"', end='') |
|
|
|
else: |
|
if args.length < 0: |
|
for chunk in iter(lambda: fp.read(1024), b''): |
|
make_hex(chunk) |
|
else: |
|
remainder = args.length |
|
for chunk in iter(lambda: fp.read(min(1024, remainder)), b''): |
|
make_hex(chunk) |
|
remainder = remainder - len(chunk) |
|
|
|
|
|
if __name__ == "__main__": |
|
main()
|
|
|