#pragma once #include "endianness.h" #include #include #include #include namespace BK64 { // Reads the fields after a resource's 64-byte header, swapping when the header names the other byte order. Throws // when it runs out. class ResourceReader { public: explicit ResourceReader(const std::vector& bytes) : mBytes(bytes) { if (bytes.size() < 0x40) { throw std::runtime_error("the resource is under 64 bytes"); } mSwap = (bytes[0] == (uint8_t)Torch::Endianness::Big) != (Torch::Endianness::Native == Torch::Endianness::Big); } template void Read(T& value) { if (mBytes.size() - mAt < sizeof(T)) { throw std::runtime_error("the resource ends early"); } for (size_t i = 0; i < sizeof(T); i++) { ((uint8_t*)&value)[mSwap ? sizeof(T) - 1 - i : i] = mBytes[mAt + i]; } mAt += sizeof(T); } template T Read() { T value; Read(value); return value; } template void ReadArray(T* values, size_t count) { for (size_t i = 0; i < count; i++) { Read(values[i]); } } std::vector Bytes(size_t size) { if (mBytes.size() - mAt < size) { throw std::runtime_error("the resource ends early"); } mAt += size; return std::vector(mBytes.begin() + (mAt - size), mBytes.begin() + mAt); } private: const std::vector& mBytes; size_t mAt = 0x40; bool mSwap = false; }; } // namespace BK64