vulkan/shaders: manually indent bin2array
[platform/upstream/gstreamer.git] / ext / vulkan / shaders / bin2array.py
1 #!/usr/bin/env python3
2 import binascii
3 import sys
4 import os
5 import argparse
6
7 autogenerated_notice = """/*
8  * This file is autogenerated by bin2array.py
9  */
10 """
11
12 def make_sublist_group (lst: list, grp: int) -> list:
13     """
14     Group list elements into sublists.
15     make_sublist_group([1, 2, 3, 4, 5, 6, 7], 3) = [[1, 2, 3], [4, 5, 6], 7]
16     """
17     return [lst[i:i+grp] for i in range(0, len(lst), grp)]
18
19 def generate_c_array_data (bindata: bytes,
20                            element_prefix: str,
21                            element_size: int,
22                            element_suffix: str,
23                            newline_value: str,
24                            newline_after: int,
25                            element_separator: str) -> str:
26     """
27     Generate the contents of a C array as a hex string
28     e.g:
29     0x10, 0x20, 0x30, 0x40,
30     0x50, 0x60, 0x70, 0x80,
31     """
32     hexstr = binascii.hexlify(bindata).decode("UTF-8")
33     array = []
34     for i in range(0, len(hexstr), 2 * element_size):
35         array += [element_prefix + hexstr[i:i + 2 * element_size] + element_suffix]
36
37     if newline_after:
38         array = make_sublist_group(array, newline_after)
39     else:
40         array = [array,]
41
42     return newline_value.join([element_separator.join(e) + element_separator for e in array])
43
44 def decorate_c_array_data (hexdata: str,
45                            var_name: str,
46                            var_type: str,
47                            newline_value: str):
48     """
49     Place @hexdata into a valid C array named @var_name of C type @var_type.
50     """
51     ret = var_type + " " + var_name + "[] = {" + newline_value
52     ret += hexdata + newline_value
53     ret += "};" + newline_value
54     return ret
55
56 def main(args):
57     parser = argparse.ArgumentParser(description='Convert binary file to C-style array initializer.')
58     parser.add_argument("-i", "--input", help="the file to be converted")
59     parser.add_argument("--output", help="c source file location")
60     parser.add_argument("--header-output", help="c header file location")
61     parser.add_argument("--linebreak", type=int, help="add linebreak after every N element")
62     parser.add_argument("--linebreak-value", default="\n", help="use what sequence to break lines, defaults to \"\\n\"")
63     parser.add_argument("--separator", default=", ", help="use what to separate elements, defaults to \", \"")
64     parser.add_argument("--array-name", default="array_data", help="name of the resulting array")
65     parser.add_argument("--element-type", default="char", help="C type for the array")
66     parser.add_argument("--element-size", type=int, default=1, help="how many bytes per element")
67     parser.add_argument("--element-prefix", default="0x", help="string to be added to the head of element, defaults to \"0x\"")
68     parser.add_argument("--element-suffix", default="", help="string to be added to the tail of element, defaults to none")
69     parser.add_argument("--c-include", help="header to include")
70     args = parser.parse_args(args)
71
72     with open(args.input, 'rb') as f:
73         file_content = f.read()
74
75     # don't deal with unaligned content
76     assert len(file_content) % args.element_size == 0
77
78     # get a relative path from the source file to the header to use in an #include
79     source_to_header = os.path.relpath (os.path.dirname (args.header_output),
80                                         os.path.dirname (args.output))
81
82     ret = autogenerated_notice
83     ret += "#include \""
84     ret += os.path.join (source_to_header,
85                          os.path.basename (args.header_output))
86     ret += "\"" + args.linebreak_value
87
88     arr_data = generate_c_array_data (file_content,
89                                       args.element_prefix,
90                                       args.element_size,
91                                       args.element_suffix,
92                                       args.linebreak_value,
93                                       args.linebreak,
94                                       args.separator)
95     ret += decorate_c_array_data (arr_data,
96                                   args.array_name,
97                                   args.element_type,
98                                   args.linebreak_value)
99
100     with open (args.output, 'w') as f:
101         f.write (ret)
102
103     # write companion header
104     with open(args.header_output, 'w') as f:
105         f.write (autogenerated_notice)
106         if args.c_include:
107             f.write ("#include <" + args.c_include + ">" + args.linebreak_value)
108         f.write ("extern " + args.element_type + " " + args.array_name + "[];" + args.linebreak_value)
109         f.write ("#define " + args.array_name + "_size " + str(len(file_content) // args.element_size))
110
111 if __name__ == "__main__":
112     sys.exit(main(sys.argv[1:]))