-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscrapper.py
163 lines (138 loc) · 4.47 KB
/
scrapper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/env python3
import argparse, pathlib, json, os
import utils
def __write_if_needed(text: str, output: pathlib.Path) -> None:
new = text.encode()
if output.is_file():
old = output.read_bytes()
if old != new:
print(f"Updating file: {output}")
output.write_bytes(new)
else:
print(f"Writing file: {output}")
output.write_bytes(new)
def __write_split_header(header: list[str], output_header_file: pathlib.Path) -> None:
# * Write C++ wrapper file.
cpp_def_file = output_header_file.stem + "Impl.hpp"
cpp_def_file_path = output_header_file.parent / cpp_def_file
cpp_def_text = (
"/** @file */"
+ os.linesep
+ "#pragma once"
+ os.linesep
+ f'#include "{output_header_file.name}"'
+ os.linesep
+ header[3]
)
__write_if_needed(cpp_def_text, cpp_def_file_path)
# * Write main header file.
out = (
"/** @file */"
+ os.linesep
+ "#pragma once"
+ os.linesep
+ header[0]
+ os.linesep
+ header[1]
+ "#ifdef __cplusplus"
+ os.linesep
+ header[2]
+ f'#include "{cpp_def_file}"'
+ os.linesep
+ "#endif"
)
__write_if_needed(out, output_header_file)
def __write_combined_header(header: list[str], output_file: pathlib.Path) -> None:
out = (
"/** @file */"
+ os.linesep
+ f"#pragma once"
+ os.linesep
+ header[0]
+ os.linesep
+ header[1]
+ "#ifdef __cplusplus"
+ os.linesep
+ header[2]
+ os.linesep
+ header[3]
+ "#endif"
)
__write_if_needed(out, output_file)
def __extract_JSON(input_json: pathlib.Path) -> dict:
config = json.loads(input_json.read_text())
utils.validate_schema(config)
suffixes = utils.get_type_suffix_list(config)
config["mapping"] = suffixes
for f in config["functions"]:
if not "combination" in f:
f["combination"] = "all"
return config
def get_impl(input_json: pathlib.Path) -> str:
config = __extract_JSON(input_json)
return utils.get_impl(config)
def get_export_header(input_json: pathlib.Path) -> str:
config = __extract_JSON(input_json)
return utils.get_export_header(config)
def exec(
input_json: pathlib.Path,
separate_header: bool,
output_header_file: pathlib.Path,
output_impl_file: pathlib.Path,
) -> None:
"""Generates C and C++ wrappers from a JSON config file.
Parameters
----------
input_json : pathlib.Path
Path to the JSON config file containing the function configurations.
output_header_file : pathlib.Path
Path wherethe generated output header file will be saved.
Raises
------
ValidationError
If the JSON config does not obey the package schema.
"""
output_header_file_text = get_export_header(input_json)
output_header_file.parent.mkdir(parents=True, exist_ok=True)
if separate_header:
__write_split_header(output_header_file_text, output_header_file)
else:
__write_combined_header(output_header_file_text, output_header_file)
implementation_file_text = get_impl(input_json)
output_impl_file.parent.mkdir(parents=True, exist_ok=True)
__write_if_needed(implementation_file_text, output_impl_file)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="scrapper",
description="A script to generate c convenience wrappers for c++.",
)
parser.add_argument(
"input",
nargs=1,
help="Path to the input JSON file that describes the C++ function to generate C functions for.",
)
parser.add_argument(
"-oh",
"--output-header",
nargs=1,
required=True,
help="Path to the output header file.",
)
parser.add_argument(
"-s",
"--separate-header",
action="store_true",
help="Seperate the exported header into its interface and implementation",
)
parser.add_argument(
"-oi",
"--output-impl",
nargs=1,
required=True,
help="Path to the output implementation file.",
)
args = parser.parse_args()
input_json = pathlib.Path(args.input[0]).resolve()
output_header_file = pathlib.Path(args.output_header[0]).resolve()
output_impl_file = pathlib.Path(args.output_impl[0]).resolve()
exec(input_json, args.separate_header, output_header_file, output_impl_file)