Implemented single header reading function.
This commit is contained in:
@@ -1,8 +1,4 @@
|
|||||||
#include "esx_reader.hpp"
|
#include "esx_reader.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <bit>
|
|
||||||
|
|
||||||
using namespace esxr;
|
using namespace esxr;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -144,19 +144,19 @@ template <typename T, size_t N>
|
|||||||
concept packed = sizeof(T) == N;
|
concept packed = sizeof(T) == N;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept header = std::is_same_v<T, GroupHeader> || std::is_same_v<T, RecordHeader> || std::is_same_v<T, UnknownHeader>;
|
concept packed_header = packed<T, static_cast<std::size_t>(header_size)>;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept packed_header = header<T> && packed<T, static_cast<std::size_t>(header_size)>;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept directly_readable_header = packed_header<T> && same_endianness;
|
concept directly_readable_header = packed_header<T> && same_endianness;
|
||||||
|
|
||||||
|
constexpr bool directly_readable = directly_readable_header<UnknownHeader> && directly_readable_header<GroupHeader> && directly_readable_header<RecordHeader>;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Classes
|
// Classes
|
||||||
//
|
//
|
||||||
|
|
||||||
using Node = std::variant<GroupNode, RecordNode>;
|
using Node = std::variant<GroupNode, RecordNode>;
|
||||||
|
using Header = std::variant<RecordHeader, GroupHeader>;
|
||||||
|
|
||||||
class GroupNode {
|
class GroupNode {
|
||||||
private:
|
private:
|
||||||
@@ -189,10 +189,28 @@ constexpr FourCC fourcc_from_cstr(const char(&a)[5]) noexcept
|
|||||||
return std::bit_cast<FourCC, char[4]>(temp);
|
return std::bit_cast<FourCC, char[4]>(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void read_header(std::ifstream &in, directly_readable_header auto &out)
|
template <typename = void> requires directly_readable
|
||||||
|
[[nodiscard]] Header read_header(std::istream &in)
|
||||||
{
|
{
|
||||||
auto char_ptr = reinterpret_cast<char *>(&out);
|
// read in header
|
||||||
|
UnknownHeader unknown_header{};
|
||||||
|
auto char_ptr = reinterpret_cast<char *>(&unknown_header);
|
||||||
in.read(char_ptr, header_size);
|
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<GroupHeader, UnknownHeader>(unknown_header) };
|
||||||
|
else
|
||||||
|
return { std::bit_cast<RecordHeader, UnknownHeader>(unknown_header) };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,19 @@ static constexpr auto esm_name = "Skyrim.esm";
|
|||||||
return esm_fs;
|
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()
|
int main()
|
||||||
{
|
{
|
||||||
auto esm_fs = open_esm();
|
auto esm_fs = open_esm();
|
||||||
esxr::UnknownHeader header{};
|
auto header_variant = esxr::read_header(esm_fs);
|
||||||
esxr::read_header(esm_fs, header);
|
std::visit(utility::overloaded {
|
||||||
return static_cast<int>(esxr::fourcc_to_record_type(header.type).value());
|
[](const esxr::RecordHeader &h) { print_type(h.type); },
|
||||||
|
[](const esxr::GroupHeader& h) { print_type(h.grup); },
|
||||||
|
}, header_variant);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ constexpr std::optional<First> soa_second_to_first(const std::pair<std::array<Fi
|
|||||||
return { soa.first[index] };
|
return { soa.first[index] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For constructing visitor overload sets
|
||||||
|
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||||
|
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;
|
||||||
|
|
||||||
// Used to inspect type sizes and values at compile time. Example:
|
// Used to inspect type sizes and values at compile time. Example:
|
||||||
//
|
//
|
||||||
// TS<sizeof(Type)> x = 0;
|
// TS<sizeof(Type)> x = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user