-
Notifications
You must be signed in to change notification settings - Fork 0
/
build-headers.ts
132 lines (101 loc) · 3.64 KB
/
build-headers.ts
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
const headers = require('./lib/openvr/headers/openvr_api.json')
const fs = require('fs')
const path = require('path')
const openvr = {
enums: '',
consts: '',
structs: '',
typedefs: ''
}
const invalid_fields = ['VkDevice_T', 'VkPhysicalDevice_T', 'VkInstance_T', 'VkQueue_T', 'ID3D12Resource', 'ID3D12CommandQueue'];
const test_c_number = (str: string) => /(u?(int)+(8|16|32|64)_t)|float|double/.test(str);
for (let {enumname, values} of headers.enums) {
let out = `export enum ${enumname.replace('vr::', '')} {\n`;
for (let {name, value} of values) {
out += `\t${name} = ${value},\n`;
}
out += `}\n`;
openvr.enums += out;
}
for (let {constname, constval, consttype} of headers.consts) {
const ret = {val: (consttype.startsWith('const char')) ? constval : +constval, type: consttype}
openvr.consts += `export const ${constname} = ${typeof ret.val === "number" ? `${constval}` : `"${constval}"`};\n`;
}
//structs
const generate_type_array_contents = (type: string, repeat: number) => {
let setup = `${type}, `;
let ret = setup.repeat(repeat);
return `[${ret.slice(0, -2)}]`;
}
// generates a set 2d array from giving a type and an array of lengths
const generate_array = (inner_type: string, lengths: Array<number>): string => {
if (lengths.length === 1) {
return generate_type_array_contents(inner_type, lengths[0]);
}
const this_length = lengths.pop();
if (typeof this_length === 'undefined') return "";
return generate_array(generate_type_array_contents(inner_type, this_length), lengths);
}
const extract_lengths_from_c_array = (array_def: string) => {
const ret = array_def.split('[').map(v => +v[0]);
ret.shift();
return ret;
}
for (let {struct, fields} of headers.structs) {
switch (struct) {
case 'vr::(anonymous)':
continue;
}
let fields_result = `export type ${struct.replace('vr::', '')} = {\n`;
for (let {fieldname, fieldtype} of fields) {
let this_field_result = `${fieldname}: `;
const parse = fieldtype.split(' ');
let type_ts = '';
if (/(^struct*|^enum*)/.test(parse[0])) {
if (invalid_fields.includes(parse[1])) continue;
type_ts = parse[1].replace('vr::', '');
} else {
if (test_c_number(parse[0])) {
type_ts = 'number';
} else {
type_ts = 'any';
}
}
if (/^\[\d+\]*/.test(parse[1])) {
type_ts = generate_array(type_ts, extract_lengths_from_c_array(parse[1]));
} else if (/^\[\d+\]*/.test(parse[2])) {
type_ts = generate_array(type_ts, extract_lengths_from_c_array(parse[2]));
}
this_field_result += `${type_ts};\n`;
fields_result += `\t${this_field_result}`;
}
fields_result += `}`;
openvr.structs += `${fields_result}\n`;
}
//some typedefs are declared twice >:(
let defined_typedefs: string[] = [];
for (let {typedef, type} of headers.typedefs) {
if (defined_typedefs.includes(typedef)) continue;
defined_typedefs.push(typedef);
let type_ts = '';
//ignore
if (/(^struct*|^union*)/.test(type)) continue;
//number
if (test_c_number(type)) {
type_ts = 'number';
} else if (/^enum*/.test(type)) {
type_ts = type.replace('enum vr::', '');
} else {
type_ts = 'any';
}
openvr.typedefs += `export type ${typedef.replace('vr::', '')} = ${type_ts};\n`;
}
const file = `//enums
${openvr.enums}
//structs
${openvr.structs}
//typedefs
${openvr.typedefs}
//constants
${openvr.consts}`;
fs.writeFileSync(path.join(__dirname, 'websrc/headers.ts'), file, {encoding: 'utf-8'})