Helper for move to c++ api
This commit is contained in:
parent
754e168b48
commit
2169e3ee47
240
convert_to_cpp.py
Executable file
240
convert_to_cpp.py
Executable file
@ -0,0 +1,240 @@
|
|||||||
|
#!/bin/python3
|
||||||
|
""" A python script to transform a vulkan project to use vulkan.hpp instead of the c api
|
||||||
|
Copyright © 2022 Matthias Quintern.
|
||||||
|
This software comes with no warranty.
|
||||||
|
This software is licensed under the GPL3
|
||||||
|
"""
|
||||||
|
from os import makedirs, mkdir, path, listdir, chdir
|
||||||
|
from sys import argv, exit
|
||||||
|
import re
|
||||||
|
from bs4 import BeautifulSoup as bs
|
||||||
|
|
||||||
|
|
||||||
|
filetypes = [ ".hpp", ".cpp" ]
|
||||||
|
no_delete = False
|
||||||
|
|
||||||
|
def error(s):
|
||||||
|
print(s)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def case_to_camel(s: str) -> str:
|
||||||
|
"""
|
||||||
|
turn all letters following a uppercase letter to lowercase
|
||||||
|
turn letter following " _0-9" to uppercase
|
||||||
|
remove " " and "_"
|
||||||
|
"""
|
||||||
|
ret = ""
|
||||||
|
make_lower = False
|
||||||
|
make_upper = False
|
||||||
|
for c in s:
|
||||||
|
if c in "_ 0123456789":
|
||||||
|
make_lower = False
|
||||||
|
make_upper = True
|
||||||
|
if c in "_ ":
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
ret += c
|
||||||
|
continue
|
||||||
|
|
||||||
|
if make_lower:
|
||||||
|
ret += c.lower()
|
||||||
|
elif make_upper:
|
||||||
|
ret += c.upper()
|
||||||
|
else:
|
||||||
|
ret += c
|
||||||
|
make_upper = False
|
||||||
|
make_lower = True
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def case_first_letter_low(s: str) -> str:
|
||||||
|
return s[0].lower() + s[1:]
|
||||||
|
|
||||||
|
def delete(s) -> str:
|
||||||
|
global no_delete
|
||||||
|
if no_delete:
|
||||||
|
return "// no-delete " + s
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
enum_suffixes = [ "KHR", "EXT", "AMD", "NV"]
|
||||||
|
vk_soup = bs()
|
||||||
|
def init_enum_names():
|
||||||
|
global vk_soup
|
||||||
|
with open("vk.xml", "r") as vk:
|
||||||
|
spec = vk.read()
|
||||||
|
vk_soup = bs(spec, features="lxml")
|
||||||
|
|
||||||
|
new_token_begin_chars = r"[<>()\[\]{} ,;=&|\t\n]"
|
||||||
|
|
||||||
|
|
||||||
|
# functions that take the line and a token and return the transformed line
|
||||||
|
re_vk_function: str = new_token_begin_chars + r"(vk[A-Z][a-zA-Z]+)\("
|
||||||
|
re_vk_function_device:str = r"vk[a-zA-Z]+\(((?:device)|(?:vk.getDevice\(\))), "
|
||||||
|
def vk_function(line:str, function:str) -> str:
|
||||||
|
match = re.search(re_vk_function_device, line)
|
||||||
|
if match:
|
||||||
|
new_function:str = match.groups()[0] + "." + case_first_letter_low(function.removeprefix("vk"))
|
||||||
|
return line.replace(match.groups()[0] + ", ", "").replace(function, new_function)
|
||||||
|
else:
|
||||||
|
new_function = "vk::" + case_first_letter_low(function.removeprefix("vk"))
|
||||||
|
return line.replace(function, new_function)
|
||||||
|
|
||||||
|
re_vk_type: str = new_token_begin_chars + r"(Vk[A-Z][a-zA-Z]+)"
|
||||||
|
def vk_type(line:str, type_:str) -> str:
|
||||||
|
new_type = "vk::" + type_.removeprefix("Vk")
|
||||||
|
return line.replace(type_, new_type)
|
||||||
|
|
||||||
|
# 0 -> name, 1 -> suffixes, 2 -> iteration
|
||||||
|
re_vk_enum_name: str = "Vk([a-zA-Z]+?)(?:FlagBits)?((?:KHR)|(?:EXT)|(?:AMD)|(?:NV))*([2-9]?)$"
|
||||||
|
re_vk_enum_val: str = new_token_begin_chars + r"(VK_(?:[A-Z0-9]+_)+([A-Z0-9]+))"
|
||||||
|
def vk_enum_val(line: str, enum_val: str) -> str:
|
||||||
|
new_enum_val = "vk::"
|
||||||
|
|
||||||
|
# name is VkName[FlagBits][Suffix][2] -> VK_NAME[_BIT][_SUFFIX][2]
|
||||||
|
|
||||||
|
tag = vk_soup.find(attrs={"name":enum_val})
|
||||||
|
if not tag:
|
||||||
|
print("skipping", enum_val, "(not found)")
|
||||||
|
return line
|
||||||
|
enum_val_2 = case_to_camel(enum_val)
|
||||||
|
parent = tag.parent
|
||||||
|
|
||||||
|
if not parent.attrs.__contains__("name"):
|
||||||
|
print("skipping", enum_val, "(no parent name)")
|
||||||
|
return line
|
||||||
|
|
||||||
|
# print(enum_val_2)
|
||||||
|
# print(parent["name"], parent["type"])
|
||||||
|
|
||||||
|
match = re.search(re_vk_enum_name, parent["name"])
|
||||||
|
if match:
|
||||||
|
name = match.groups()[0]
|
||||||
|
suffixes = match.groups()[1]
|
||||||
|
iteration = match.groups()[2]
|
||||||
|
# enum name
|
||||||
|
new_enum_val += parent["name"].removeprefix("Vk") + "::"
|
||||||
|
# enum val name
|
||||||
|
print("\tenum_val_2", enum_val_2)
|
||||||
|
print("\tname", name)
|
||||||
|
print("\tparent['name']", parent['name'])
|
||||||
|
print("\tsuffixes", suffixes)
|
||||||
|
print("\titeration", iteration)
|
||||||
|
new_enum_val += "e" + enum_val_2.removeprefix("Vk" + name)
|
||||||
|
if suffixes:
|
||||||
|
new_enum_val = new_enum_val.removesuffix(case_to_camel(suffixes))
|
||||||
|
new_enum_val = new_enum_val.removesuffix("Bit")
|
||||||
|
else:
|
||||||
|
print("skipping", enum_val, "(no parent name match)")
|
||||||
|
return line
|
||||||
|
print(new_enum_val, "\n")
|
||||||
|
return line.replace(enum_val, new_enum_val)
|
||||||
|
|
||||||
|
def vk_str(line, m):
|
||||||
|
# same match with different group
|
||||||
|
match = re.search(r"STR_VK_[A-Z]+\((.+)\)", line)
|
||||||
|
if match:
|
||||||
|
return line.replace(m, match.groups()[0])
|
||||||
|
else:
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
# f = f(line, match_group) -> line
|
||||||
|
re_and_f = {
|
||||||
|
re_vk_function: vk_function,
|
||||||
|
re_vk_type: vk_type,
|
||||||
|
re_vk_enum_val: vk_enum_val,
|
||||||
|
r"(STR_VK_[A-Z]+\(.+\))": vk_str,
|
||||||
|
}
|
||||||
|
|
||||||
|
re_vk_struct_init: str = r"vk::[a-zA-Z2]+ [a-zA-Z]+ ?\{\};"
|
||||||
|
def vk_struct_init(s):
|
||||||
|
return s.replace("};", "").replace("{", " {").replace(" {", " {")
|
||||||
|
|
||||||
|
re_vk_struct_member_init: str = r"([a-zA-Z]+(?:(?:CI)|(?:AI)|(?:I)|(?:MI)))\.[a-zA-Z0-9]+ = .+;"
|
||||||
|
def vk_struct_member_init(s):
|
||||||
|
match= re.search(re_vk_struct_member_init, s)
|
||||||
|
if match:
|
||||||
|
return s.replace(match.groups()[0], "\t").replace(";", ",")
|
||||||
|
else:
|
||||||
|
return s
|
||||||
|
|
||||||
|
# f = f(line) -> line
|
||||||
|
re_no_group_and_f = {
|
||||||
|
"#include <vulkan/vulkan_core.h>": lambda l : "#define VULKAN_HPP_NO_CONSTRUCTORS\n" + l.replace("vulkan_core.h>", "vulkan.hpp>"),
|
||||||
|
r"\.sType ?=": lambda l : delete(l),
|
||||||
|
"VK_SUCCESS": lambda l : l.replace("VK_SUCCESS", "vk::Result::eSuccess"),
|
||||||
|
re_vk_struct_init: vk_struct_init,
|
||||||
|
re_vk_struct_member_init: vk_struct_member_init,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def transform_file(filename:str, outfilename):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("transform_file:", filename)
|
||||||
|
if not path.isfile(filename): error("File does not exist:" + filename)
|
||||||
|
|
||||||
|
with open(filename, "r") as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
|
||||||
|
for i in range(len(lines)):
|
||||||
|
line = lines[i]
|
||||||
|
for reg, f in re_and_f.items():
|
||||||
|
for m in re.finditer(reg, line):
|
||||||
|
line = f(line, m.groups()[0])
|
||||||
|
|
||||||
|
line = line
|
||||||
|
for reg, f in re_no_group_and_f.items():
|
||||||
|
if re.search(reg, line):
|
||||||
|
line = f(line)
|
||||||
|
lines[i] = line
|
||||||
|
|
||||||
|
with open(outfilename, "w") as file:
|
||||||
|
file.writelines(lines)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# with open(filename, "w") as file:
|
||||||
|
# file.writelines(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def process_path(path_):
|
||||||
|
# print("Processing path:", path_)
|
||||||
|
if path.isfile(path_) and path.splitext(path_)[-1] in filetypes:
|
||||||
|
makedirs("new/" + path.dirname(path_), exist_ok=True)
|
||||||
|
transform_file(path_, "new/" + path_)
|
||||||
|
else:
|
||||||
|
if path.isdir(path_):
|
||||||
|
for p in listdir(path_):
|
||||||
|
process_path(path_ + "/" + p)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def print_help():
|
||||||
|
print("""
|
||||||
|
-h --help help
|
||||||
|
--no-delete comment lines instead of deleting them"""
|
||||||
|
)
|
||||||
|
|
||||||
|
def missing_arg(arg):
|
||||||
|
print("Missing argument for", arg)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
i = 1
|
||||||
|
while i in range(1, len(argv)):
|
||||||
|
if argv[i] == "--help" or argv[i] == "-h":
|
||||||
|
print_help()
|
||||||
|
exit(0)
|
||||||
|
elif argv[i] == "--no-delete":
|
||||||
|
no_delete = True
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
init_enum_names()
|
||||||
|
process_path(path.curdir)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user