From 0048df18751f63848a2935f4114f4d08ac57a56c Mon Sep 17 00:00:00 2001 From: William Miles Date: Mon, 24 Oct 2022 20:37:40 +1100 Subject: [PATCH] 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. --- Navmesher/esx_reader.hpp | 12 +- Navmesher/esx_reader_lut.cpp | 43 ++-- ...r.hpp.fragment => esx_reader.fragment.hpp} | 15 +- reference/esx_reader_lut.cpp | 70 ++++--- reference/record_codegen.py | 196 +++++++++++------- 5 files changed, 192 insertions(+), 144 deletions(-) rename reference/{esx_reader.hpp.fragment => esx_reader.fragment.hpp} (57%) diff --git a/Navmesher/esx_reader.hpp b/Navmesher/esx_reader.hpp index 20496e7..31cf7c4 100644 --- a/Navmesher/esx_reader.hpp +++ b/Navmesher/esx_reader.hpp @@ -154,12 +154,12 @@ private: // Free functions // -[[nodiscard]] extern constexpr std::optional group_type_to_name(GroupType group_type) noexcept; -[[nodiscard]] extern constexpr std::optional record_type_to_fourcc(RecordType record_type) noexcept; -[[nodiscard]] extern constexpr std::optional fourcc_to_record_type(FourCC fourcc) noexcept; -[[nodiscard]] extern constexpr std::optional record_type_to_name(RecordType record_type) noexcept; -[[nodiscard]] extern constexpr std::optional flag_to_description(Flag flag) noexcept; -[[nodiscard]] extern constexpr std::optional refr_flag_to_description(RefrFlag refr_flag) noexcept; +[[nodiscard]] std::optional group_type_to_name(GroupType group_type) noexcept; +[[nodiscard]] std::optional record_type_to_fourcc(RecordType record_type) noexcept; +[[nodiscard]] std::optional fourcc_to_record_type(FourCC fourcc) noexcept; +[[nodiscard]] std::optional record_type_to_name(RecordType record_type) noexcept; +[[nodiscard]] std::optional flag_to_description(Flag flag) noexcept; +[[nodiscard]] std::optional refr_flag_to_description(RefrFlag refr_flag) noexcept; } diff --git a/Navmesher/esx_reader_lut.cpp b/Navmesher/esx_reader_lut.cpp index 37a6d2e..ed57cdd 100644 --- a/Navmesher/esx_reader_lut.cpp +++ b/Navmesher/esx_reader_lut.cpp @@ -14,8 +14,6 @@ static constexpr std::pair 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 record_type_fourcc_map_builtin[] { {RecordType::AACT, FourCC("AACT")}, {RecordType::ACHR, FourCC("ACHR")}, @@ -87,8 +85,6 @@ static constexpr std::pair 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 record_type_name_map_builtin[] { {RecordType::AACT, "Action" }, @@ -228,8 +224,6 @@ static constexpr std::pair 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_description_map_builtin[] { {{RecordType::ACHR, 9}, "Starts Dead" }, @@ -400,8 +394,6 @@ static constexpr std::pair 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 refr_flag_description_map_builtin[] { {{RecordType::ACTI, 9}, "Hidden From Local Map" }, @@ -582,34 +574,47 @@ static constexpr std::pair 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 group_type_to_name(GroupType group_type) noexcept +[[nodiscard]] std::optional 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 record_type_to_fourcc(RecordType record_type) noexcept + +[[nodiscard]] std::optional 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 fourcc_to_record_type(FourCC fourcc) noexcept +[[nodiscard]] std::optional esxr::fourcc_to_record_type(FourCC fourcc) noexcept { return utility::soa_second_to_first(record_type_fourcc_map, fourcc); } -[[nodiscard]] constexpr std::optional record_type_to_name(RecordType record_type) noexcept + +[[nodiscard]] std::optional 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 flag_to_description(Flag flag) noexcept + +[[nodiscard]] std::optional esxr::flag_to_description(Flag flag) noexcept { return utility::soa_first_to_second(flag_description_map, flag); } -[[nodiscard]] constexpr std::optional refr_flag_to_description(RefrFlag refr_flag) noexcept + +[[nodiscard]] std::optional esxr::refr_flag_to_description(RefrFlag refr_flag) noexcept { return utility::soa_first_to_second(refr_flag_description_map, refr_flag); -} - -} +} \ No newline at end of file diff --git a/reference/esx_reader.hpp.fragment b/reference/esx_reader.fragment.hpp similarity index 57% rename from reference/esx_reader.hpp.fragment rename to reference/esx_reader.fragment.hpp index 418cb64..6fc78e2 100644 --- a/reference/esx_reader.hpp.fragment +++ b/reference/esx_reader.fragment.hpp @@ -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 group_type_to_name(GroupType group_type) noexcept; -[[nodiscard]] constexpr std::optional record_type_to_fourcc(RecordType record_type) noexcept; -[[nodiscard]] constexpr std::optional fourcc_to_record_type(FourCC fourcc) noexcept; -[[nodiscard]] constexpr std::optional record_type_to_name(RecordType record_type) noexcept; -[[nodiscard]] constexpr std::optional flag_to_description(Flag flag) noexcept; -[[nodiscard]] constexpr std::optional refr_flag_to_description(RefrFlag refr_flag) noexcept; \ No newline at end of file + WEAP, WOOP, WRLD, WTHR, +}; +[[nodiscard]] std::optional group_type_to_name(GroupType group_type) noexcept +[[nodiscard]] std::optional record_type_to_fourcc(RecordType record_type) noexcept +[[nodiscard]] std::optional fourcc_to_record_type(FourCC fourcc) noexcept +[[nodiscard]] std::optional record_type_to_name(RecordType record_type) noexcept +[[nodiscard]] std::optional flag_to_description(Flag flag) noexcept +[[nodiscard]] std::optional refr_flag_to_description(RefrFlag refr_flag) noexcept \ No newline at end of file diff --git a/reference/esx_reader_lut.cpp b/reference/esx_reader_lut.cpp index 373ad7c..ed57cdd 100644 --- a/reference/esx_reader_lut.cpp +++ b/reference/esx_reader_lut.cpp @@ -2,8 +2,6 @@ using namespace esxr; -namespace esxr_lut { - static constexpr std::pair group_type_name_map_builtin[] { {GroupType::Top , "Top Type" }, {GroupType::WorldChildren , "World Children" }, @@ -16,12 +14,6 @@ static constexpr std::pair 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 group_type_to_name(GroupType group_type) noexcept -{ - return utility::soa_first_to_second(group_type_name_map, group_type); -} static constexpr std::pair record_type_fourcc_map_builtin[] { {RecordType::AACT, FourCC("AACT")}, {RecordType::ACHR, FourCC("ACHR")}, @@ -93,16 +85,6 @@ static constexpr std::pair 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 record_type_to_fourcc(RecordType record_type) noexcept -{ - return utility::soa_first_to_second(record_type_fourcc_map, record_type); -} -[[nodiscard]] constexpr std::optional fourcc_to_record_type(FourCC fourcc) noexcept -{ - return utility::soa_second_to_first(record_type_fourcc_map, fourcc); -} static constexpr std::pair record_type_name_map_builtin[] { {RecordType::AACT, "Action" }, @@ -242,12 +224,6 @@ static constexpr std::pair 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 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_description_map_builtin[] { {{RecordType::ACHR, 9}, "Starts Dead" }, @@ -418,12 +394,6 @@ static constexpr std::pair 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 flag_to_description(Flag flag) noexcept -{ - return utility::soa_first_to_second(flag_description_map, flag); -} static constexpr std::pair refr_flag_description_map_builtin[] { {{RecordType::ACTI, 9}, "Hidden From Local Map" }, @@ -604,11 +574,47 @@ static constexpr std::pair 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 refr_flag_to_description(RefrFlag refr_flag) noexcept + +[[nodiscard]] std::optional 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 esxr::record_type_to_fourcc(RecordType record_type) noexcept +{ + return utility::soa_first_to_second(record_type_fourcc_map, record_type); } +[[nodiscard]] std::optional esxr::fourcc_to_record_type(FourCC fourcc) noexcept +{ + return utility::soa_second_to_first(record_type_fourcc_map, fourcc); +} + +[[nodiscard]] std::optional esxr::record_type_to_name(RecordType record_type) noexcept +{ + return utility::soa_first_to_second(record_type_name_map, record_type); +} + +[[nodiscard]] std::optional esxr::flag_to_description(Flag flag) noexcept +{ + return utility::soa_first_to_second(flag_description_map, flag); +} + +[[nodiscard]] std::optional esxr::refr_flag_to_description(RefrFlag refr_flag) noexcept +{ + return utility::soa_first_to_second(refr_flag_description_map, refr_flag); +} \ No newline at end of file diff --git a/reference/record_codegen.py b/reference/record_codegen.py index bb3c377..0032313 100644 --- a/reference/record_codegen.py +++ b/reference/record_codegen.py @@ -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)