diff --git a/Navmesher/esx_reader.cpp b/Navmesher/esx_reader.cpp index 8be5d7f..f278348 100644 --- a/Navmesher/esx_reader.cpp +++ b/Navmesher/esx_reader.cpp @@ -1,8 +1,4 @@ #include "esx_reader.hpp" -#include -#include - using namespace esxr; - diff --git a/Navmesher/esx_reader.hpp b/Navmesher/esx_reader.hpp index 3128297..0f7400f 100644 --- a/Navmesher/esx_reader.hpp +++ b/Navmesher/esx_reader.hpp @@ -144,19 +144,19 @@ template concept packed = sizeof(T) == N; template -concept header = std::is_same_v || std::is_same_v || std::is_same_v; - -template -concept packed_header = header && packed(header_size)>; +concept packed_header = packed(header_size)>; template concept directly_readable_header = packed_header && same_endianness; +constexpr bool directly_readable = directly_readable_header && directly_readable_header && directly_readable_header; + // // Classes // using Node = std::variant; +using Header = std::variant; class GroupNode { private: @@ -189,10 +189,28 @@ constexpr FourCC fourcc_from_cstr(const char(&a)[5]) noexcept return std::bit_cast(temp); } -inline void read_header(std::ifstream &in, directly_readable_header auto &out) +template requires directly_readable +[[nodiscard]] Header read_header(std::istream &in) { - auto char_ptr = reinterpret_cast(&out); + // read in header + UnknownHeader unknown_header{}; + auto char_ptr = reinterpret_cast(&unknown_header); in.read(char_ptr, header_size); + auto type_opt = fourcc_to_record_type(unknown_header.type); + + // failed to read header + if (in.fail()) + throw std::runtime_error("Could not read header from given input stream.") + + // invalid type value + if (!type_opt) + throw std::runtime_error("Invalid header type while reading esx file."); + + auto type = type_opt.value(); + if (type == RecordType::GRUP) + return { std::bit_cast(unknown_header) }; + else + return { std::bit_cast(unknown_header) }; } } diff --git a/Navmesher/main.cpp b/Navmesher/main.cpp index 85e0344..1b768cc 100644 --- a/Navmesher/main.cpp +++ b/Navmesher/main.cpp @@ -21,10 +21,19 @@ static constexpr auto esm_name = "Skyrim.esm"; return esm_fs; } +void print_type(esxr::FourCC fcc) +{ + auto type = esxr::fourcc_to_record_type(fcc).value(); + auto name = esxr::record_type_to_name(type); + std::cout << name.value() << '\n'; +} + int main() { auto esm_fs = open_esm(); - esxr::UnknownHeader header{}; - esxr::read_header(esm_fs, header); - return static_cast(esxr::fourcc_to_record_type(header.type).value()); + auto header_variant = esxr::read_header(esm_fs); + std::visit(utility::overloaded { + [](const esxr::RecordHeader &h) { print_type(h.type); }, + [](const esxr::GroupHeader& h) { print_type(h.grup); }, + }, header_variant); } diff --git a/Navmesher/utility.hpp b/Navmesher/utility.hpp index 379626e..bb85365 100644 --- a/Navmesher/utility.hpp +++ b/Navmesher/utility.hpp @@ -66,6 +66,10 @@ constexpr std::optional soa_second_to_first(const std::pair struct overloaded : Ts... { using Ts::operator()...; }; +template overloaded(Ts...)->overloaded; + // Used to inspect type sizes and values at compile time. Example: // // TS x = 0;