#pragma once #include #include #include #include #include "../utility/endian.hpp" template requires std::is_arithmetic_v struct vec2 { T X; T Y; vec2() = default; vec2(const T& val) : X(val), Y(val) {} }; template requires std::is_arithmetic_v struct vec3 { T X; T Y; T Z; vec3() = default; vec3(const T& val) : X(val), Y(val), Z(val) {} vec3(const T& x_, const T& y_, const T& z_) : X(x_), Y(y_), Z(z_) {} }; template requires std::is_arithmetic_v struct vec4 { T A; T B; T C; T D; vec4() = default; vec4(const T& val) : A(val), B(val), C(val), D(val) {} }; template bool readVec2(std::istream& in, const std::streamoff offset, vec2& out) { in.seekg(offset, std::ios::beg); if (!in.read(reinterpret_cast(&out.X), sizeof(out.X))) return false; if (!in.read(reinterpret_cast(&out.Y), sizeof(out.Y))) return false; if constexpr (sizeof(T) > 1) { Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.X); Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.Y); } return true; } template void writeVec2(std::ostream& out, const vec2& vec) { if constexpr (sizeof(T) > 1) { T X_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.X); T Y_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.Y); out.write(reinterpret_cast(&X_BE), sizeof(X_BE)); out.write(reinterpret_cast(&Y_BE), sizeof(Y_BE)); return; } else { out.write(reinterpret_cast(&vec.X), sizeof(vec.X)); out.write(reinterpret_cast(&vec.Y), sizeof(vec.Y)); return; } } template bool readVec3(std::istream& in, const std::streamoff offset, vec3& out) { in.seekg(offset, std::ios::beg); if (!in.read(reinterpret_cast(&out.X), sizeof(out.X))) return false; if (!in.read(reinterpret_cast(&out.Y), sizeof(out.Y))) return false; if (!in.read(reinterpret_cast(&out.Z), sizeof(out.Z))) return false; if constexpr (sizeof(T) > 1) { Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.X); Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.Y); Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.Z); } return true; } template void writeVec3(std::ostream& out, const vec3& vec) { if constexpr (sizeof(T) > 1) { T X_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.X); T Y_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.Y); T Z_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.Z); out.write(reinterpret_cast(&X_BE), sizeof(X_BE)); out.write(reinterpret_cast(&Y_BE), sizeof(Y_BE)); out.write(reinterpret_cast(&Z_BE), sizeof(Z_BE)); return; } else { out.write(reinterpret_cast(&vec.X), sizeof(vec.X)); out.write(reinterpret_cast(&vec.Y), sizeof(vec.Y)); out.write(reinterpret_cast(&vec.Z), sizeof(vec.Z)); return; } } template bool readVec4(std::istream& in, const std::streamoff offset, vec4& out) { in.seekg(offset, std::ios::beg); if (!in.read(reinterpret_cast(&out.A), sizeof(out.A))) return false; if (!in.read(reinterpret_cast(&out.B), sizeof(out.B))) return false; if (!in.read(reinterpret_cast(&out.C), sizeof(out.C))) return false; if (!in.read(reinterpret_cast(&out.D), sizeof(out.D))) return false; if constexpr (sizeof(T) > 1) { Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.A); Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.B); Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.C); Utility::Endian::toPlatform_inplace(Utility::Endian::Type::Big, out.D); } return true; } template void writeVec4(std::ostream& out, const vec4& vec) { if constexpr (sizeof(T) > 1) { T A_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.A); T B_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.B); T C_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.C); T D_BE = Utility::Endian::toPlatform(Utility::Endian::Type::Big, vec.D); out.write(reinterpret_cast(&A_BE), sizeof(A_BE)); out.write(reinterpret_cast(&B_BE), sizeof(B_BE)); out.write(reinterpret_cast(&C_BE), sizeof(C_BE)); out.write(reinterpret_cast(&D_BE), sizeof(D_BE)); return; } else { out.write(reinterpret_cast(&vec.A), sizeof(vec.A)); out.write(reinterpret_cast(&vec.B), sizeof(vec.B)); out.write(reinterpret_cast(&vec.C), sizeof(vec.C)); out.write(reinterpret_cast(&vec.D), sizeof(vec.D)); return; } } std::string readNullTerminatedStr(std::istream& in, const unsigned int& offset); std::u16string readNullTerminatedWStr(std::istream& in, const unsigned int offset); template requires requires { requires std::is_enum_v; error_enum::NONE; error_enum::REACHED_EOF; error_enum::UNEXPECTED_VALUE; } error_enum readPadding(std::istream& in, const unsigned int& len, const char* val = nullptr) { if (in.tellg() % len != 0) { const size_t& padding_size = len - (static_cast(in.tellg()) % len); std::string padding(padding_size, '\0'); if (!in.read(&padding[0], static_cast(padding_size))) return error_enum::REACHED_EOF; if(val != nullptr) { for (const char& character : padding) { if (character != *val) return error_enum::UNEXPECTED_VALUE; } } } return error_enum::NONE; } size_t padToLen(std::ostream& out, const unsigned int& len, const char pad = '\x00');