Skip to content

Commit f3d513d

Browse files
hIAhmadkartben
authored andcommitted
scripts: build: Add support for generating string literals in file2hex.py
Currently, file2hex.py supports conversion of binary data into hexadecimal character list format only. The generated list can then be used to embed the binary data by using the list to initialize an array. However, this approach is highly inefficient for large binary files. A close but considerably more efficient alternative is to use string literals composed of hex characters (in escaped form) to initialize the array, instead of an initializer list. Benchmarking (with GCC and clang) indicates that compile time and host memory usage by the compiler can be more than an order of magnitude less with string literal approach compared to the initializer list form. The only caveat is that string literals contain the null character as terminator so where accurate length is required, the correct length must be specified explicitly while defining the array. Signed-off-by: Irfan Ahmad <[email protected]>
1 parent b10587f commit f3d513d

File tree

1 file changed

+32
-7
lines changed

1 file changed

+32
-7
lines changed

scripts/build/file2hex.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22
#
33
# Copyright (c) 2017 Intel Corporation
4+
# Copyright (c) 2025 Siemens AG
45
#
56
# SPDX-License-Identifier: Apache-2.0
67

@@ -31,6 +32,8 @@ def parse_args():
3132
parser.add_argument("-l", "--length", type=lambda x: int(x, 0), default=-1,
3233
help="""Length in bytes to read from the input file.
3334
Defaults to reading till the end of the input file.""")
35+
parser.add_argument("-m", "--format", default="list",
36+
help="Output format: 'list' (default) or 'literal' (string literal)")
3437
parser.add_argument("-g", "--gzip", action="store_true",
3538
help="Compress the file using gzip before output")
3639
parser.add_argument("-t", "--gzip-mtime", type=int, default=0,
@@ -56,6 +59,12 @@ def make_hex(chunk):
5659
print(get_nice_string(hexlist) + ',')
5760

5861

62+
def make_string_literal(chunk):
63+
hexdata = codecs.encode(chunk, 'hex').decode("utf-8")
64+
hexlist = map(''.join, zip(*[iter(hexdata)] * 2))
65+
print(''.join("\\x" + str(x) for x in hexlist), end='')
66+
67+
5968
def main():
6069
parse_args()
6170

@@ -74,14 +83,30 @@ def main():
7483
else:
7584
with open(args.file, "rb") as fp:
7685
fp.seek(args.offset)
77-
if args.length < 0:
78-
for chunk in iter(lambda: fp.read(1024), b''):
79-
make_hex(chunk)
86+
87+
if args.format == "literal":
88+
if args.length < 0:
89+
print('"', end='')
90+
for chunk in iter(lambda: fp.read(1024), b''):
91+
make_string_literal(chunk)
92+
print('"', end='')
93+
else:
94+
print('"', end='')
95+
remainder = args.length
96+
for chunk in iter(lambda: fp.read(min(1024, remainder)), b''):
97+
make_string_literal(chunk)
98+
remainder = remainder - len(chunk)
99+
print('"', end='')
100+
80101
else:
81-
remainder = args.length
82-
for chunk in iter(lambda: fp.read(min(1024, remainder)), b''):
83-
make_hex(chunk)
84-
remainder = remainder - len(chunk)
102+
if args.length < 0:
103+
for chunk in iter(lambda: fp.read(1024), b''):
104+
make_hex(chunk)
105+
else:
106+
remainder = args.length
107+
for chunk in iter(lambda: fp.read(min(1024, remainder)), b''):
108+
make_hex(chunk)
109+
remainder = remainder - len(chunk)
85110

86111

87112
if __name__ == "__main__":

0 commit comments

Comments
 (0)