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:
2022-10-24 20:37:40 +11:00
parent 188b462e68
commit 0048df1875
5 changed files with 192 additions and 144 deletions

View File

@@ -154,12 +154,12 @@ private:
// Free functions
//
[[nodiscard]] extern constexpr std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept;
[[nodiscard]] extern constexpr std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept;
[[nodiscard]] extern constexpr std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept;
[[nodiscard]] extern constexpr std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept;
[[nodiscard]] extern constexpr std::optional<std::string_view> flag_to_description(Flag flag) noexcept;
[[nodiscard]] extern constexpr std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept;
[[nodiscard]] std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept;
[[nodiscard]] std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept;
[[nodiscard]] std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept;
[[nodiscard]] std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept;
[[nodiscard]] std::optional<std::string_view> flag_to_description(Flag flag) noexcept;
[[nodiscard]] std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept;
}

View File

@@ -14,8 +14,6 @@ static constexpr std::pair<GroupType, std::string_view> group_type_name_map_buil
{GroupType::CellPersistentChildren, "Cell Persistent Children"},
{GroupType::CellTemporaryChildren , "Cell Temporary Children" },
};
static constexpr auto group_type_name_map_std = utility::array_builtin_to_std(group_type_name_map_builtin);
static constexpr auto group_type_name_map = utility::map_to_soa(group_type_name_map_std);
static constexpr std::pair<RecordType, FourCC> record_type_fourcc_map_builtin[] {
{RecordType::AACT, FourCC("AACT")}, {RecordType::ACHR, FourCC("ACHR")},
@@ -87,8 +85,6 @@ static constexpr std::pair<RecordType, FourCC> record_type_fourcc_map_builtin[]
{RecordType::WEAP, FourCC("WEAP")}, {RecordType::WOOP, FourCC("WOOP")},
{RecordType::WRLD, FourCC("WRLD")}, {RecordType::WTHR, FourCC("WTHR")},
};
static constexpr auto record_type_fourcc_map_std = utility::array_builtin_to_std(record_type_fourcc_map_builtin);
static constexpr auto record_type_fourcc_map = utility::map_to_soa(record_type_fourcc_map_std);
static constexpr std::pair<RecordType, std::string_view> record_type_name_map_builtin[] {
{RecordType::AACT, "Action" },
@@ -228,8 +224,6 @@ static constexpr std::pair<RecordType, std::string_view> record_type_name_map_bu
{RecordType::WRLD, "Worldspace" },
{RecordType::WTHR, "Weather" },
};
static constexpr auto record_type_name_map_std = utility::array_builtin_to_std(record_type_name_map_builtin);
static constexpr auto record_type_name_map = utility::map_to_soa(record_type_name_map_std);
static constexpr std::pair<Flag, std::string_view> flag_description_map_builtin[] {
{{RecordType::ACHR, 9}, "Starts Dead" },
@@ -400,8 +394,6 @@ static constexpr std::pair<Flag, std::string_view> flag_description_map_builtin[
{{RecordType::WEAP, 2}, "Non-Playable" },
{{RecordType::WRLD, 19}, "Can't Wait" },
};
static constexpr auto flag_description_map_std = utility::array_builtin_to_std(flag_description_map_builtin);
static constexpr auto flag_description_map = utility::map_to_soa(flag_description_map_std);
static constexpr std::pair<RefrFlag, std::string_view> refr_flag_description_map_builtin[] {
{{RecordType::ACTI, 9}, "Hidden From Local Map" },
@@ -582,34 +574,47 @@ static constexpr std::pair<RefrFlag, std::string_view> refr_flag_description_map
{{RecordType::WEAP, 30}, "No Respawn" },
{{RecordType::WEAP, 31}, "Multibound" },
};
static constexpr auto group_type_name_map_std = utility::array_builtin_to_std(group_type_name_map_builtin);
static constexpr auto group_type_name_map = utility::map_to_soa(group_type_name_map_std);
static constexpr auto record_type_fourcc_map_std = utility::array_builtin_to_std(record_type_fourcc_map_builtin);
static constexpr auto record_type_fourcc_map = utility::map_to_soa(record_type_fourcc_map_std);
static constexpr auto record_type_name_map_std = utility::array_builtin_to_std(record_type_name_map_builtin);
static constexpr auto record_type_name_map = utility::map_to_soa(record_type_name_map_std);
static constexpr auto flag_description_map_std = utility::array_builtin_to_std(flag_description_map_builtin);
static constexpr auto flag_description_map = utility::map_to_soa(flag_description_map_std);
static constexpr auto refr_flag_description_map_std = utility::array_builtin_to_std(refr_flag_description_map_builtin);
static constexpr auto refr_flag_description_map = utility::map_to_soa(refr_flag_description_map_std);
namespace esxr {
[[nodiscard]] constexpr std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept
[[nodiscard]] std::optional<std::string_view> esxr::group_type_to_name(GroupType group_type) noexcept
{
return utility::soa_first_to_second(group_type_name_map, group_type);
}
[[nodiscard]] constexpr std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept
[[nodiscard]] std::optional<FourCC> esxr::record_type_to_fourcc(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_fourcc_map, record_type);
}
[[nodiscard]] constexpr std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept
[[nodiscard]] std::optional<RecordType> esxr::fourcc_to_record_type(FourCC fourcc) noexcept
{
return utility::soa_second_to_first(record_type_fourcc_map, fourcc);
}
[[nodiscard]] constexpr std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept
[[nodiscard]] std::optional<std::string_view> esxr::record_type_to_name(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_name_map, record_type);
}
[[nodiscard]] constexpr std::optional<std::string_view> flag_to_description(Flag flag) noexcept
[[nodiscard]] std::optional<std::string_view> esxr::flag_to_description(Flag flag) noexcept
{
return utility::soa_first_to_second(flag_description_map, flag);
}
[[nodiscard]] constexpr std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept
[[nodiscard]] std::optional<std::string_view> esxr::refr_flag_to_description(RefrFlag refr_flag) noexcept
{
return utility::soa_first_to_second(refr_flag_description_map, refr_flag);
}
}
}

View File

@@ -10,10 +10,11 @@ enum class RecordType {
PHZD, PLYR, PMIS, PROJ, PWAT, QUST, RACE, REFR, REGN, RELA, REVB, RFCT,
RGDL, SCEN, SCOL, SCPT, SCRL, SHOU, SLGM, SMBN, SMEN, SMQN, SNCT, SNDR,
SOPM, SOUN, SPEL, SPGD, STAT, TACT, TES4, TREE, TXST, VOLI, VTYP, WATR,
WEAP, WOOP, WRLD, WTHR, };
[[nodiscard]] constexpr std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept;
[[nodiscard]] constexpr std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept;
[[nodiscard]] constexpr std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> flag_to_description(Flag flag) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept;
WEAP, WOOP, WRLD, WTHR,
};
[[nodiscard]] std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept
[[nodiscard]] std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept
[[nodiscard]] std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept
[[nodiscard]] std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept
[[nodiscard]] std::optional<std::string_view> flag_to_description(Flag flag) noexcept
[[nodiscard]] std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept

View File

@@ -2,8 +2,6 @@
using namespace esxr;
namespace esxr_lut {
static constexpr std::pair<GroupType, std::string_view> group_type_name_map_builtin[] {
{GroupType::Top , "Top Type" },
{GroupType::WorldChildren , "World Children" },
@@ -16,12 +14,6 @@ static constexpr std::pair<GroupType, std::string_view> group_type_name_map_buil
{GroupType::CellPersistentChildren, "Cell Persistent Children"},
{GroupType::CellTemporaryChildren , "Cell Temporary Children" },
};
static constexpr auto group_type_name_map_std = utility::array_builtin_to_std(group_type_name_map_builtin);
static constexpr auto group_type_name_map = utility::map_to_soa(group_type_name_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept
{
return utility::soa_first_to_second(group_type_name_map, group_type);
}
static constexpr std::pair<RecordType, FourCC> record_type_fourcc_map_builtin[] {
{RecordType::AACT, FourCC("AACT")}, {RecordType::ACHR, FourCC("ACHR")},
@@ -93,16 +85,6 @@ static constexpr std::pair<RecordType, FourCC> record_type_fourcc_map_builtin[]
{RecordType::WEAP, FourCC("WEAP")}, {RecordType::WOOP, FourCC("WOOP")},
{RecordType::WRLD, FourCC("WRLD")}, {RecordType::WTHR, FourCC("WTHR")},
};
static constexpr auto record_type_fourcc_map_std = utility::array_builtin_to_std(record_type_fourcc_map_builtin);
static constexpr auto record_type_fourcc_map = utility::map_to_soa(record_type_fourcc_map_std);
[[nodiscard]] constexpr std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_fourcc_map, record_type);
}
[[nodiscard]] constexpr std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept
{
return utility::soa_second_to_first(record_type_fourcc_map, fourcc);
}
static constexpr std::pair<RecordType, std::string_view> record_type_name_map_builtin[] {
{RecordType::AACT, "Action" },
@@ -242,12 +224,6 @@ static constexpr std::pair<RecordType, std::string_view> record_type_name_map_bu
{RecordType::WRLD, "Worldspace" },
{RecordType::WTHR, "Weather" },
};
static constexpr auto record_type_name_map_std = utility::array_builtin_to_std(record_type_name_map_builtin);
static constexpr auto record_type_name_map = utility::map_to_soa(record_type_name_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_name_map, record_type);
}
static constexpr std::pair<Flag, std::string_view> flag_description_map_builtin[] {
{{RecordType::ACHR, 9}, "Starts Dead" },
@@ -418,12 +394,6 @@ static constexpr std::pair<Flag, std::string_view> flag_description_map_builtin[
{{RecordType::WEAP, 2}, "Non-Playable" },
{{RecordType::WRLD, 19}, "Can't Wait" },
};
static constexpr auto flag_description_map_std = utility::array_builtin_to_std(flag_description_map_builtin);
static constexpr auto flag_description_map = utility::map_to_soa(flag_description_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> flag_to_description(Flag flag) noexcept
{
return utility::soa_first_to_second(flag_description_map, flag);
}
static constexpr std::pair<RefrFlag, std::string_view> refr_flag_description_map_builtin[] {
{{RecordType::ACTI, 9}, "Hidden From Local Map" },
@@ -604,11 +574,47 @@ static constexpr std::pair<RefrFlag, std::string_view> refr_flag_description_map
{{RecordType::WEAP, 30}, "No Respawn" },
{{RecordType::WEAP, 31}, "Multibound" },
};
static constexpr auto group_type_name_map_std = utility::array_builtin_to_std(group_type_name_map_builtin);
static constexpr auto group_type_name_map = utility::map_to_soa(group_type_name_map_std);
static constexpr auto record_type_fourcc_map_std = utility::array_builtin_to_std(record_type_fourcc_map_builtin);
static constexpr auto record_type_fourcc_map = utility::map_to_soa(record_type_fourcc_map_std);
static constexpr auto record_type_name_map_std = utility::array_builtin_to_std(record_type_name_map_builtin);
static constexpr auto record_type_name_map = utility::map_to_soa(record_type_name_map_std);
static constexpr auto flag_description_map_std = utility::array_builtin_to_std(flag_description_map_builtin);
static constexpr auto flag_description_map = utility::map_to_soa(flag_description_map_std);
static constexpr auto refr_flag_description_map_std = utility::array_builtin_to_std(refr_flag_description_map_builtin);
static constexpr auto refr_flag_description_map = utility::map_to_soa(refr_flag_description_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept
[[nodiscard]] std::optional<std::string_view> esxr::group_type_to_name(GroupType group_type) noexcept
{
return utility::soa_first_to_second(refr_flag_description_map, refr_flag);
return utility::soa_first_to_second(group_type_name_map, group_type);
}
[[nodiscard]] std::optional<FourCC> esxr::record_type_to_fourcc(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_fourcc_map, record_type);
}
[[nodiscard]] std::optional<RecordType> esxr::fourcc_to_record_type(FourCC fourcc) noexcept
{
return utility::soa_second_to_first(record_type_fourcc_map, fourcc);
}
[[nodiscard]] std::optional<std::string_view> esxr::record_type_to_name(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_name_map, record_type);
}
[[nodiscard]] std::optional<std::string_view> esxr::flag_to_description(Flag flag) noexcept
{
return utility::soa_first_to_second(flag_description_map, flag);
}
[[nodiscard]] std::optional<std::string_view> esxr::refr_flag_to_description(RefrFlag refr_flag) noexcept
{
return utility::soa_first_to_second(refr_flag_description_map, refr_flag);
}

View File

@@ -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)