Fixed odr violation from trying to separate constexpr functions into declaration and definition in separate files. Modified code gen to be in line with current code.
This commit is contained in:
@@ -7,18 +7,13 @@ INDENT = 8
|
||||
WIDTH = 80
|
||||
LAST = "};"
|
||||
SV = "std::string_view"
|
||||
|
||||
PREAMBLE = """#include "esx_reader.hpp"
|
||||
|
||||
using namespace esxr;
|
||||
|
||||
namespace esxr_lut {"""
|
||||
POSTAMBLE = "}\n"
|
||||
NS = "esxr::"
|
||||
PREAMBLE = '#include "esx_reader.hpp"\n\nusing namespace esxr;'
|
||||
|
||||
|
||||
def transpose(seq):
|
||||
return list(zip(*seq))
|
||||
|
||||
|
||||
def clean(seq):
|
||||
return [x for x in seq if x is not None]
|
||||
|
||||
@@ -36,15 +31,12 @@ def indented_block(items):
|
||||
lines += [line]
|
||||
return "\n".join(lines)
|
||||
|
||||
def indented_list(items):
|
||||
return ",\n".join([" " * INDENT + x for x in items])
|
||||
|
||||
def max_length(list):
|
||||
return max(map(lambda x: len(x), list))
|
||||
|
||||
def wrap_bracket(list):
|
||||
return ["{" + string + "}" for string in list]
|
||||
|
||||
|
||||
def padded_join(lists):
|
||||
maximums = [max_length(x) for x in lists]
|
||||
padded = []
|
||||
@@ -59,56 +51,71 @@ class Map:
|
||||
second_type: str
|
||||
first_name: str
|
||||
second_name: str
|
||||
reverse: bool
|
||||
formats: list[str]
|
||||
|
||||
data: dict
|
||||
|
||||
F_DECL = "static constexpr std::pair<{0}, {1}> {2}_builtin[] {{"
|
||||
F_SOA = """static constexpr auto {0}_std = utility::array_builtin_to_std({0}_builtin);
|
||||
static constexpr auto {0} = utility::map_to_soa({0}_std);"""
|
||||
F_FUNC_DECL = "[[nodiscard]] constexpr std::optional<{0}> {1}_to_{2}({3} {1}) noexcept"
|
||||
F_FUNC_DECL = "[[nodiscard]] std::optional<{0}> {4}{1}_to_{2}({3} {1}) noexcept"
|
||||
F_FUNC_BODY_FORWARD = " return utility::soa_first_to_second({0}, {1});"
|
||||
F_FUNC_BODY_REVERSE = " return utility::soa_second_to_first({0}, {1});"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.first_name + "_" + self.second_name + "_map"
|
||||
|
||||
|
||||
@property
|
||||
def decl(self):
|
||||
return Map.F_DECL.format(self.first_type, self.second_type, self.name)
|
||||
|
||||
|
||||
@property
|
||||
def to_soa(self):
|
||||
return Map.F_SOA.format(self.name)
|
||||
|
||||
|
||||
def _forward_decl(self, namespace=""):
|
||||
return Map.F_FUNC_DECL.format(self.second_type, self.first_name, self.second_name, self.first_type, namespace)
|
||||
|
||||
def _reverse_decl(self, namespace=""):
|
||||
return Map.F_FUNC_DECL.format(self.first_type, self.second_name, self.first_name, self.second_type, namespace)
|
||||
|
||||
@property
|
||||
def forward_decl(self):
|
||||
return Map.F_FUNC_DECL.format(self.second_type, self.first_name, self.second_name, self.first_type)
|
||||
|
||||
return self._forward_decl()
|
||||
|
||||
@property
|
||||
def reverse_decl(self):
|
||||
return Map.F_FUNC_DECL.format(self.first_type, self.second_name, self.first_name, self.second_type)
|
||||
|
||||
return self._reverse_decl()
|
||||
|
||||
@property
|
||||
def func_decls(self):
|
||||
decls = [self.forward_decl] + ([self.reverse_decl] if self.reverse else [])
|
||||
return "\n".join(decls)
|
||||
|
||||
@property
|
||||
def forward_func(self):
|
||||
return self.forward_decl + "\n{\n" + Map.F_FUNC_BODY_FORWARD.format(self.name, self.first_name) + "\n}"
|
||||
|
||||
return self._forward_decl(NS) + "\n{\n" + Map.F_FUNC_BODY_FORWARD.format(self.name, self.first_name) + "\n}"
|
||||
|
||||
@property
|
||||
def reverse_func(self):
|
||||
return self.reverse_decl + "\n{\n" + Map.F_FUNC_BODY_REVERSE.format(self.name, self.second_name) + "\n}"
|
||||
|
||||
return self._reverse_decl(NS) + "\n{\n" + Map.F_FUNC_BODY_REVERSE.format(self.name, self.second_name) + "\n}"
|
||||
|
||||
@property
|
||||
def funcs(self):
|
||||
f = [self.forward_func] + ([self.reverse_func] if self.reverse else [])
|
||||
return "\n".join(f)
|
||||
|
||||
def data_to_list(self, data):
|
||||
parts = []
|
||||
for format in self.formats:
|
||||
parts += [[format.format(*x) for x in data]]
|
||||
return indented_block(wrap_bracket(padded_join(parts)))
|
||||
|
||||
def code(self, data, reverse = False):
|
||||
parts = [self.decl, self.data_to_list(data), LAST, self.to_soa, self.forward_func]
|
||||
decls = [self.forward_decl]
|
||||
if reverse:
|
||||
parts += [self.reverse_func]
|
||||
decls += [self.reverse_decl]
|
||||
return ["\n".join(parts), "\n".join([x + ';' for x in decls])]
|
||||
|
||||
@property
|
||||
def lut(self):
|
||||
parts = [self.decl, self.data_to_list(self.data), LAST]
|
||||
return "\n".join(parts)
|
||||
|
||||
|
||||
def add_extra(data):
|
||||
@@ -117,61 +124,90 @@ def add_extra(data):
|
||||
data += [grup, note]
|
||||
data.sort(key=lambda x: x["fourcc"])
|
||||
|
||||
|
||||
# read in our data sets
|
||||
fdir = os.path.dirname(__file__)
|
||||
|
||||
with open(os.path.join(fdir, "records.json"), "r") as f:
|
||||
record_data = json.load(f)
|
||||
add_extra(record_data)
|
||||
|
||||
with open(os.path.join(fdir, "refr_flags.json"), "r") as f:
|
||||
refr_data = json.load(f)
|
||||
|
||||
with open(os.path.join(fdir, "group_type.json"), "r") as f:
|
||||
group_type_data = json.load(f)
|
||||
|
||||
|
||||
# create our maps
|
||||
group_name_map = Map(
|
||||
first_type = "GroupType",
|
||||
second_type = SV,
|
||||
first_name = "group_type",
|
||||
second_name = "name",
|
||||
reverse = False,
|
||||
formats = ["GroupType::{0}", ", \"{1}\""],
|
||||
data = [(x['type'], x['name']) for x in group_type_data]
|
||||
)
|
||||
record_name_map = Map(
|
||||
first_type = "RecordType",
|
||||
second_type = SV,
|
||||
first_name = "record_type",
|
||||
second_name = "name",
|
||||
reverse = False,
|
||||
formats = ["RecordType::{0}", ", \"{1}\""],
|
||||
data = [(x['fourcc'], x['name']) for x in record_data]
|
||||
)
|
||||
record_fourcc_map = Map(
|
||||
first_type = "RecordType",
|
||||
second_type = "FourCC",
|
||||
first_name = "record_type",
|
||||
second_name = "fourcc",
|
||||
reverse = True,
|
||||
formats = ["RecordType::{0}", ", FourCC(\"{0}\")"],
|
||||
data = [(x['fourcc'], ) for x in record_data]
|
||||
)
|
||||
flag_desc_map = Map(
|
||||
first_type = "Flag",
|
||||
second_type = SV,
|
||||
first_name = "flag",
|
||||
second_name = "description",
|
||||
reverse = False,
|
||||
formats = ["{{RecordType::{0}, {1:>2}}}", ", \"{2}\""],
|
||||
data = [(x['fourcc'], y['bit'], y['description']) for x in record_data for y in x['flags']]
|
||||
)
|
||||
refr_flag_desc_map = Map(
|
||||
first_type = "RefrFlag",
|
||||
second_type = SV,
|
||||
first_name = "refr_flag",
|
||||
second_name = "description",
|
||||
reverse = False,
|
||||
formats = ["{{RecordType::{0}, {1:>2}}}", ", \"{2}\""],
|
||||
data = [(x['fourcc'], y['bit'], y['description']) for x in refr_data for y in x['flags']]
|
||||
)
|
||||
|
||||
maps = [group_name_map, record_fourcc_map, record_name_map, flag_desc_map, refr_flag_desc_map]
|
||||
|
||||
def gen_enum(data):
|
||||
# generate sorted list of signatures
|
||||
sigs = [r["fourcc"] for r in data]
|
||||
string = "enum class RecordType {\n" + indented_block(sigs) + LAST
|
||||
return [None, string]
|
||||
|
||||
def gen_group_type(data):
|
||||
map = Map("GroupType", SV, "group_type", "name", ["GroupType::{0}", ", \"{1}\""])
|
||||
data = [(x['type'], x['name']) for x in data]
|
||||
return map.code(data)
|
||||
|
||||
def gen_names(data):
|
||||
map = Map("RecordType", SV, "record_type", "name", ["RecordType::{0}", ", \"{1}\""])
|
||||
data = [(x['fourcc'], x['name']) for x in data]
|
||||
return map.code(data)
|
||||
|
||||
def gen_fourcc(data):
|
||||
map = Map("RecordType", "FourCC", "record_type", "fourcc", ["RecordType::{0}", ", FourCC(\"{0}\")"])
|
||||
data = [(x['fourcc'], ) for x in data]
|
||||
return map.code(data, reverse = True)
|
||||
|
||||
def gen_flags(data):
|
||||
map = Map("Flag", SV, "flag", "description", ["{{RecordType::{0}, {1:>2}}}", ", \"{2}\""])
|
||||
data = [(x['fourcc'], y['bit'], y['description']) for x in data for y in x['flags']]
|
||||
return map.code(data)
|
||||
|
||||
def gen_refr_flags(data):
|
||||
map = Map("RefrFlag", SV, "refr_flag", "description", ["{{RecordType::{0}, {1:>2}}}", ", \"{2}\""])
|
||||
data = [(x['fourcc'], y['bit'], y['description']) for x in data for y in x['flags']]
|
||||
return map.code(data)
|
||||
string = "\n".join(("enum class RecordType {", indented_block(sigs), LAST))
|
||||
return string
|
||||
|
||||
def main():
|
||||
fdir = os.path.dirname(__file__)
|
||||
with open(os.path.join(fdir, "records.json"), "r") as f:
|
||||
data = json.load(f)
|
||||
with open(os.path.join(fdir, "refr_flags.json"), "r") as f:
|
||||
refr_data = json.load(f)
|
||||
with open(os.path.join(fdir, "group_type.json"), "r") as f:
|
||||
gt_data = json.load(f)
|
||||
add_extra(data)
|
||||
code = []
|
||||
code += [gen_enum(data)]
|
||||
code += [gen_group_type(gt_data)]
|
||||
code += [gen_fourcc(data)]
|
||||
code += [gen_names(data)]
|
||||
code += [gen_flags(data)]
|
||||
code += [gen_refr_flags(refr_data)]
|
||||
code = transpose(code)
|
||||
lut = [PREAMBLE] + clean(code[0]) + [POSTAMBLE]
|
||||
lut = [PREAMBLE]
|
||||
lut += map(lambda m: m.lut, maps)
|
||||
lut += map(lambda m: m.to_soa, maps)
|
||||
lut += map(lambda m: m.funcs, maps)
|
||||
lut = "\n\n".join(lut)
|
||||
header = clean(code[1])
|
||||
header = "\n".join(header)
|
||||
with open(os.path.join(fdir, "esx_reader_lut.cpp"), "w") as f:
|
||||
f.write(lut)
|
||||
with open(os.path.join(fdir, "esx_reader.hpp.fragment"), "w") as f:
|
||||
|
||||
header = []
|
||||
header += [gen_enum(record_data)]
|
||||
header += map(lambda m: m.func_decls, maps)
|
||||
header = "\n".join(header)
|
||||
with open(os.path.join(fdir, "esx_reader.fragment.hpp"), "w") as f:
|
||||
f.write(header)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user