diff --git a/Navmesher/Navmesher.vcxproj b/Navmesher/Navmesher.vcxproj index 08d21a6..7dba576 100644 --- a/Navmesher/Navmesher.vcxproj +++ b/Navmesher/Navmesher.vcxproj @@ -140,6 +140,7 @@ + diff --git a/Navmesher/Navmesher.vcxproj.filters b/Navmesher/Navmesher.vcxproj.filters index b8424dd..732cb89 100644 --- a/Navmesher/Navmesher.vcxproj.filters +++ b/Navmesher/Navmesher.vcxproj.filters @@ -32,5 +32,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/Navmesher/esx_reader.cpp b/Navmesher/esx_reader.cpp index f278348..edd8db5 100644 --- a/Navmesher/esx_reader.cpp +++ b/Navmesher/esx_reader.cpp @@ -1,4 +1,9 @@ -#include "esx_reader.hpp" +#include "esx_reader_impl.hpp" using namespace esxr; +[[nodiscard]] Header esxr::read_header(std::istream &in) +{ + return read_header_impl(in); +} + diff --git a/Navmesher/esx_reader.hpp b/Navmesher/esx_reader.hpp index 0f7400f..245848a 100644 --- a/Navmesher/esx_reader.hpp +++ b/Navmesher/esx_reader.hpp @@ -21,14 +21,6 @@ namespace esxr { class GroupNode; class RecordNode; -// -// Constants -// - -static constexpr auto esx_endianness = std::endian::little; -static constexpr std::streamsize header_size = 24; -static constexpr bool same_endianness = std::endian::native == esx_endianness; - // // Enumerations // @@ -136,21 +128,6 @@ struct RecordHeader { uint16_t unknown; }; -// -// Concepts -// - -template -concept packed = sizeof(T) == N; - -template -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 // @@ -181,37 +158,7 @@ private: [[nodiscard]] std::optional flag_to_description(Flag flag) noexcept; [[nodiscard]] std::optional refr_flag_to_description(RefrFlag refr_flag) noexcept; - -// Convert a compatible C string to a FourCC (e.g. "LITR") -constexpr FourCC fourcc_from_cstr(const char(&a)[5]) noexcept -{ - char temp[4] = { a[0], a[1], a[2], a[3] }; - return std::bit_cast(temp); -} - -template requires directly_readable -[[nodiscard]] Header read_header(std::istream &in) -{ - // 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) }; -} +[[nodiscard]] Header read_header(std::istream &in); } diff --git a/Navmesher/esx_reader_impl.hpp b/Navmesher/esx_reader_impl.hpp new file mode 100644 index 0000000..24ba0cc --- /dev/null +++ b/Navmesher/esx_reader_impl.hpp @@ -0,0 +1,63 @@ +#ifndef ESX_READER_IMPL_HPP +#define ESX_READER_IMPL_HPP + +#include "esx_reader.hpp" + +namespace esxr { + +// +// Constants and Concepts +// + +static constexpr auto esx_endianness = std::endian::little; +static constexpr std::streamsize header_size = 24; +static constexpr bool same_endianness = std::endian::native == esx_endianness; + +template +concept packed = sizeof(T) == N; + +template +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; + +// +// Template functions +// + +template requires directly_readable +[[nodiscard]] Header read_header_impl(std::istream &in) +{ + // 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) }; +} + +template requires (!directly_readable) +[[nodiscard]] Header read_header_impl(std::istream &in) +{ + static_assert(directly_readable, "Not implemented."); +} + +} + +#endif /* ESX_READER_IMPL_HPP */ \ No newline at end of file diff --git a/Navmesher/esx_reader_lut.cpp b/Navmesher/esx_reader_lut.cpp index 60dcd08..1b84bdc 100644 --- a/Navmesher/esx_reader_lut.cpp +++ b/Navmesher/esx_reader_lut.cpp @@ -15,6 +15,13 @@ static constexpr std::pair group_type_name_map_buil {GroupType::CellTemporaryChildren , "Cell Temporary Children" }, }; +// Convert a compatible C string to a FourCC (e.g. "LITR") +static consteval FourCC fourcc_from_cstr(const char(&a)[5]) noexcept +{ + char temp[4] = { a[0], a[1], a[2], a[3] }; + return std::bit_cast(temp); +} + static constexpr std::pair record_type_fourcc_map_builtin[] { {RecordType::AACT, fourcc_from_cstr("AACT")}, {RecordType::ACHR, fourcc_from_cstr("ACHR")},