import json import os def resolve_enum_size(size): if (size == 1): return "byte" if (size == 4): return "int" raise Exception("Unknown size {}".format(size)) def clean_namespace(namespace): if (namespace == "Pkmnlib_ai"): return "PkmnLibAI" return namespace def write_enum(enum, enumNames): namespace = str.capitalize(enum["filename"][3:]) if (namespace == "Pkmnlib_ai"): return if (enum["name"].startswith("bfd_")): return if (enum["name"].startswith("float_")): return if (enum["name"].startswith("as")): return if (enum["name"][0] >= 'a' and enum["name"][0] <= 'z'): return if (enum["name"] == "EPOLL_EVENTS"): return; if (enum["name"] == "METADATATYPE"): return; filename = "Generated/{}/{}.cs".format(clean_namespace(namespace), enum["name"]) os.makedirs(os.path.dirname(filename), exist_ok=True) with open(filename, "w") as f: f.write("// AUTOMATICALLY GENERATED, DO NOT EDIT\n") f.write("using System.Diagnostics.CodeAnalysis;\n\n") f.write("namespace {}\n{{\n".format(namespace)) f.write(" [SuppressMessage(\"ReSharper\", \"InconsistentNaming\")]\n") f.write(" internal enum {} : {}\n {{\n".format(enum["name"], resolve_enum_size(enum["byteSize"]) )) vals = enum["values"].items() dict = {} for k, v in vals: dict[int(k)] = v for k, v in sorted(dict.items(), key=lambda item: item[0]): if (enum["byteSize"] == 1 and k < 0): k = 256 + k f.write(" {} = {},\n".format(v, k)) f.write(" }\n") f.write("}\n") enumNames.add(enum["name"]) class funcDef: def __init__(self, name, returns, parameters): self.name = name self.returns = returns self.parameters = parameters class classDef: def __init__(self, namespace, name, file): self.namespace = namespace self.file = file self.name = name self.functions = [] def register_function(self, func): self.functions.append(func) def parse_function(function, classDict): splitName = function["name"].split("_") classKey = "{}_{}".format(function["filename"], splitName[1]) if (not classKey in classDict): classDict[classKey] = classDef(function["filename"][3:].capitalize(), splitName[1], function["filename"]) classDict[classKey].register_function(funcDef(function["name"], function["returns"], function["parameters"])) def parse_type(type, enumSet): type = type.strip() if (type == "void"): return "void" if (type == "unsigned char"): return "byte" if (type == "signed char"): return "sbyte" if (type == "unsigned short"): return "ushort" if (type == "bool"): return "byte" if (type == "float"): return "float" if (type == "double"): return "double" if (type == "long unsigned int"): return "ulong" if (type == "long int"): return "long" if (type == "unsigned int"): return "uint" if (type == "int"): return "int" if (type.endswith("*")): return "IntPtr" if (type.endswith("&")): return "ref " + parse_type(type[:-1], enumSet) if (type in enumSet): return type print("Unhandled type '{}'".format(type)) return "IntPtr" def clean_name(name): if (name == "out"): return "@out" if (name == "event"): return "@event" if (name == ""): return "_" return name def write_class(c, enumSet): filename = "Generated/{}/{}.cs".format(clean_namespace(c.file[3:].capitalize()), c.name) os.makedirs(os.path.dirname(filename), exist_ok=True) with open(filename, "w") as f: f.write("// AUTOMATICALLY GENERATED, DO NOT EDIT\n") f.write("using System;\n") f.write("using System.Runtime.InteropServices;\n\n") f.write("namespace {}.Generated\n{{\n".format(clean_namespace(c.namespace))) f.write(" internal static class {}\n {{\n".format(c.name)) for function in c.functions: for parameter in function.parameters: f.write(" /// {}\n".format(parameter["name"], parameter["type"])) f.write(" /// {}\n".format(function.returns)) f.write(" [DllImport(\"{}\", CallingConvention = CallingConvention.Cdecl, EntryPoint= \"{}\")]\n".format(c.file, function.name)) f.write(" internal static extern {} {}(".format(parse_type(function.returns, enumSet), function.name.split("_")[2])) isFirst = True for parameter in function.parameters: if (not isFirst): f.write(", ") else: isFirst = False f.write("{} {}".format(parse_type(parameter["type"], enumSet), clean_name(parameter["name"]))) f.write(");\n\n") f.write(" }\n") f.write("}\n") def parse_create(data, filepath): enumSet = set() for enum in data["enums"]: write_enum(enum, enumSet) classDict = dict() for function in data["functions"]: parse_function(function, classDict) print("Registered {} classes from file {}.".format(len(classDict), filepath)) for _, v in classDict.items(): write_class(v, enumSet) def handle_file(filepath): with open(filepath) as json_file: data = json.load(json_file) parse_create(data, filepath) def main(): handle_file("arbutils.json") handle_file("creaturelib.json") handle_file("pkmnlib.json") handle_file("pkmnlibai.json") main()