-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgenstructs.py
More file actions
118 lines (100 loc) · 4.31 KB
/
genstructs.py
File metadata and controls
118 lines (100 loc) · 4.31 KB
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
#!/usr/bin/env python3
from xml.dom.minidom import parse
def is_int(x):
try:
int(x)
return True
except ValueError:
return False
def output_warning(file):
file.write('''================= DO NOT EDIT THIS FILE ====================
This file has been automatically generated by genstructs.py
Please edit structs.xml instead, and re-run genstructs.py
============================================================
''')
def generate_header(struct):
struct_name = struct.getAttribute('name')
if not struct_name:
print('ERROR: struct definition without a name')
exit(1)
file = open(f"src/Structs/{struct_name}.hpp", "w")
file.write(f'#ifndef {struct_name.upper()}_HPP\n#define {struct_name.upper()}_HPP\n/*\n')
output_warning(file)
file.write('*/\n#include "StructLoader.hpp"\n')
for dep in struct.getElementsByTagName('dependency'):
dep_file = dep.getAttribute('name')
if not dep_file:
print('ERROR: struct dependency without a name')
print(f' in struct {struct_name}')
exit(1)
file.write(f'#include "{dep_file}"\n')
file.write(f'struct {struct_name} {{\n')
for field in struct.getElementsByTagName('field'):
field_name = field.getAttribute('name')
field_type = field.getAttribute('type')
field_count = field.getAttribute('count')
field_max_count = field.getAttribute('max-count')
if not field_name:
print('ERROR: struct field without a name')
print(f' in struct {struct_name}')
exit(1)
if not field_type:
print(f'ERROR: struct field {field_name} without a type')
print(f' in struct {struct_name}')
exit(1)
if not field_count and not field_max_count:
file.write(f' {field_type} {field_name};\n')
elif is_int(field_count):
file.write(f' std::array<{field_type}, {field_count}> {field_name};\n')
else:
file.write(f' std::vector<{field_type}> {field_name};\n')
for extra in struct.getElementsByTagName('extra'):
file.write(extra.firstChild.wholeText)
file.write(f'''}};
template <> struct StructLoader<{struct_name}> {{
static const char* readBuffer(const char *begin, const char *end, {struct_name} &output) {{
if (begin > end) {{
throw DLSynth::Error("Wrong data size", DLSynth::ErrorCode::INVALID_FILE);
}}
const char *cur_pos = begin;
''')
for field in struct.getElementsByTagName('field'):
field_name = field.getAttribute('name')
field_type = field.getAttribute('type')
field_count = field.getAttribute('count')
field_max_count = field.getAttribute('max-count')
field_offset = field.getAttribute('offset')
if not field_count and not field_max_count:
file.write(f' cur_pos = StructLoader<{field_type}>::readBuffer(cur_pos, end, output.{field_name});\n')
elif is_int(field_count):
if not field_offset:
file.write(f' cur_pos = readArray<{field_type}>(cur_pos, end, output.{field_name});\n')
else:
field.write(f''' cur_pos = begin + output.{field_offset};
cur_pos = readArray<{field_type}>(cur_pos, end, output.{field_name});
''')
elif not is_int(field_count) and not field_max_count:
if not field_offset:
file.write(f''' output.{field_name}.resize(output.{field_count});
cur_pos = readArray<{field_type}>(cur_pos, end, output.{field_count}, output.{field_name});
''')
else:
file.write(f''' cur_pos = begin + output.{field_offset};
output.{field_name}.resize(output.{field_count});
cur_pos = readArray<{field_type}>(cur_pos, end, output.{field_count}, output.{field_name});
''')
else:
file.write(f''' {{
std::size_t count = 0;
while (count < output.{field_max_count} && cur_pos < end) {{
{field_type} elem;
cur_pos = StructLoader<{field_type}>::readBuffer(cur_pos, end, elem);
output.{field_name}.push_back(elem);
}}
}}
''')
file.write(' return cur_pos;\n }\n};\n#endif\n')
file.close()
structs = parse('structs.xml')
for struct in structs.getElementsByTagName('struct'):
generate_header(struct)