refactor: Make use of the StreamReader in the BinaryFile
This commit is contained in:
parent
a182063e2e
commit
0d9962dc50
6 changed files with 99 additions and 192 deletions
|
@ -17,8 +17,6 @@
|
|||
|
||||
#include "binfile.h"
|
||||
|
||||
#include <codecvt>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
@ -59,6 +57,7 @@ void BinaryFile::load(const shared_ptr<istream> &in) {
|
|||
throw invalid_argument("Invalid input stream");
|
||||
}
|
||||
_in = in;
|
||||
_reader = make_unique<StreamReader>(in, _endianess);
|
||||
|
||||
load();
|
||||
}
|
||||
|
@ -90,172 +89,91 @@ void BinaryFile::load(const fs::path &path) {
|
|||
if (!fs::exists(path)) {
|
||||
throw runtime_error("File not found: " + path.string());
|
||||
}
|
||||
_in.reset(new fs::ifstream(path, ios::binary));
|
||||
_in = make_shared<fs::ifstream>(path, ios::binary);
|
||||
_reader = make_unique<StreamReader>(_in, _endianess);
|
||||
_path = path;
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
uint32_t BinaryFile::tell() const {
|
||||
return static_cast<uint32_t>(_in->tellg());
|
||||
return _reader->tell();
|
||||
}
|
||||
|
||||
void BinaryFile::ignore(int size) {
|
||||
_in->ignore(size);
|
||||
_reader->ignore(size);
|
||||
}
|
||||
|
||||
uint8_t BinaryFile::readByte() {
|
||||
uint8_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 1);
|
||||
return val;
|
||||
return _reader->getByte();
|
||||
}
|
||||
|
||||
int16_t BinaryFile::readInt16() {
|
||||
int16_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 2);
|
||||
return val;
|
||||
}
|
||||
|
||||
int16_t BinaryFile::readInt16BE() {
|
||||
int16_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 2);
|
||||
return ((val << 8) & 0xff00) | ((val >> 8) & 0x00ff);
|
||||
return _reader->getInt16();
|
||||
}
|
||||
|
||||
uint16_t BinaryFile::readUint16() {
|
||||
uint16_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 2);
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16_t BinaryFile::readUint16BE() {
|
||||
uint16_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 2);
|
||||
return ((val << 8) & 0xff00) | ((val >> 8) & 0x00ff);
|
||||
return _reader->getUint16();
|
||||
}
|
||||
|
||||
int32_t BinaryFile::readInt32() {
|
||||
int32_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 4);
|
||||
return val;
|
||||
}
|
||||
|
||||
int32_t BinaryFile::readInt32BE() {
|
||||
int32_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 4);
|
||||
|
||||
return
|
||||
((val << 24) & 0xff000000) |
|
||||
((val << 8) & 0x00ff0000) |
|
||||
((val >> 8) & 0x0000ff00) |
|
||||
((val >> 24) & 0x000000ff);
|
||||
return _reader->getInt32();
|
||||
}
|
||||
|
||||
uint32_t BinaryFile::readUint32() {
|
||||
uint32_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 4);
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t BinaryFile::readUint32BE() {
|
||||
uint32_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 4);
|
||||
|
||||
return
|
||||
((val << 24) & 0xff000000) |
|
||||
((val << 8) & 0x00ff0000) |
|
||||
((val >> 8) & 0x0000ff00) |
|
||||
((val >> 24) & 0x000000ff);
|
||||
return _reader->getUint32();
|
||||
}
|
||||
|
||||
int64_t BinaryFile::readInt64() {
|
||||
int64_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 8);
|
||||
return val;
|
||||
return _reader->getInt64();
|
||||
}
|
||||
|
||||
uint64_t BinaryFile::readUint64() {
|
||||
uint64_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 8);
|
||||
return val;
|
||||
return _reader->getUint64();
|
||||
}
|
||||
|
||||
float BinaryFile::readFloat() {
|
||||
float val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 4);
|
||||
return val;
|
||||
}
|
||||
|
||||
float BinaryFile::readFloatBE() {
|
||||
uint32_t val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 4);
|
||||
val =
|
||||
((val << 24) & 0xff000000) |
|
||||
((val << 8) & 0x00ff0000) |
|
||||
((val >> 8) & 0x0000ff00) |
|
||||
((val >> 24) & 0x000000ff);
|
||||
|
||||
return *reinterpret_cast<float *>(&val);
|
||||
return _reader->getFloat();
|
||||
}
|
||||
|
||||
double BinaryFile::readDouble() {
|
||||
double val;
|
||||
_in->read(reinterpret_cast<char *>(&val), 4);
|
||||
return val;
|
||||
return _reader->getDouble();
|
||||
}
|
||||
|
||||
string BinaryFile::readFixedString(int size) {
|
||||
string s;
|
||||
s.resize(size);
|
||||
_in->read(&s[0], size);
|
||||
|
||||
return s.c_str();
|
||||
string result(_reader->getString(size));
|
||||
result.erase(find(result.begin(), result.end(), '\0'), result.end());
|
||||
return move(result);
|
||||
}
|
||||
|
||||
string BinaryFile::readFixedString(uint32_t off, int size) {
|
||||
streampos pos = _in->tellg();
|
||||
_in->seekg(off);
|
||||
size_t pos = _reader->tell();
|
||||
_reader->seek(off);
|
||||
|
||||
string s(readFixedString(size));
|
||||
_in->seekg(pos);
|
||||
string result(readFixedString(size));
|
||||
_reader->seek(pos);
|
||||
|
||||
return move(s);
|
||||
}
|
||||
|
||||
string BinaryFile::readFixedStringWide(int len) {
|
||||
u16string ws;
|
||||
ws.resize(len);
|
||||
_in->read(reinterpret_cast<char *>(&ws[0]), 2 * len);
|
||||
|
||||
wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t> conv;
|
||||
string s(conv.to_bytes(ws));
|
||||
|
||||
return move(s);
|
||||
return move(result);
|
||||
}
|
||||
|
||||
string BinaryFile::readString(uint32_t off) {
|
||||
streampos pos = _in->tellg();
|
||||
_in->seekg(off);
|
||||
size_t pos = _reader->tell();
|
||||
_reader->seek(off);
|
||||
|
||||
char buf[256];
|
||||
streamsize chRead = _in->rdbuf()->sgetn(buf, sizeof(buf));
|
||||
string result(_reader->getCString());
|
||||
_reader->seek(pos);
|
||||
|
||||
_in->seekg(pos);
|
||||
|
||||
return string(buf, strnlen(buf, chRead));
|
||||
return move(result);
|
||||
}
|
||||
|
||||
string BinaryFile::readString(uint32_t off, int size) {
|
||||
streampos pos = _in->tellg();
|
||||
_in->seekg(off);
|
||||
size_t pos = _reader->tell();
|
||||
_reader->seek(off);
|
||||
|
||||
string s;
|
||||
s.resize(size);
|
||||
string result(_reader->getString(size));
|
||||
_reader->seek(pos);
|
||||
|
||||
_in->read(&s[0], size);
|
||||
_in->seekg(pos);
|
||||
|
||||
return move(s);
|
||||
return move(result);
|
||||
}
|
||||
|
||||
} // namespace resource
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "../system/streamreader.h"
|
||||
#include "../system/types.h"
|
||||
|
||||
namespace reone {
|
||||
|
@ -34,8 +35,10 @@ public:
|
|||
void load(const boost::filesystem::path &path);
|
||||
|
||||
protected:
|
||||
Endianess _endianess { Endianess::Little };
|
||||
boost::filesystem::path _path;
|
||||
std::shared_ptr<std::istream> _in;
|
||||
std::unique_ptr<StreamReader> _reader;
|
||||
size_t _size { 0 };
|
||||
|
||||
template <typename T>
|
||||
|
@ -75,21 +78,15 @@ protected:
|
|||
void ignore(int size);
|
||||
uint8_t readByte();
|
||||
int16_t readInt16();
|
||||
int16_t readInt16BE();
|
||||
uint16_t readUint16();
|
||||
uint16_t readUint16BE();
|
||||
int32_t readInt32();
|
||||
int32_t readInt32BE();
|
||||
uint32_t readUint32();
|
||||
uint32_t readUint32BE();
|
||||
int64_t readInt64();
|
||||
uint64_t readUint64();
|
||||
float readFloat();
|
||||
float readFloatBE();
|
||||
double readDouble();
|
||||
std::string readFixedString(int size);
|
||||
std::string readFixedString(uint32_t off, int size);
|
||||
std::string readFixedStringWide(int len);
|
||||
std::string readString(uint32_t off);
|
||||
std::string readString(uint32_t off, int size);
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ KeyFile::FileEntry KeyFile::readFileEntry() {
|
|||
|
||||
FileEntry entry;
|
||||
entry.fileSize = fileSize;
|
||||
entry.filename = readString(filenameOffset, filenameSize);
|
||||
entry.filename = readFixedString(filenameOffset, filenameSize);
|
||||
|
||||
return move(entry);
|
||||
}
|
||||
|
|
|
@ -26,11 +26,12 @@ namespace reone {
|
|||
namespace script {
|
||||
|
||||
NcsFile::NcsFile(const string &resRef) : BinaryFile(8, "NCS V1.0"), _resRef(resRef) {
|
||||
_endianess = Endianess::Big;
|
||||
}
|
||||
|
||||
void NcsFile::doLoad() {
|
||||
uint8_t byteCode = readByte();
|
||||
uint32_t length = readUint32BE();
|
||||
uint32_t length = readUint32();
|
||||
|
||||
_program = make_unique<ScriptProgram>(_resRef);
|
||||
_program->_length = length;
|
||||
|
@ -57,28 +58,25 @@ void NcsFile::readInstruction(uint32_t &offset) {
|
|||
case ByteCode::CopyTopSP:
|
||||
case ByteCode::CopyDownBP:
|
||||
case ByteCode::CopyTopBP:
|
||||
ins.stackOffset = readInt32BE();
|
||||
ins.size = readUint16BE();
|
||||
break;
|
||||
|
||||
case ByteCode::Reserve:
|
||||
ins.stackOffset = readInt32();
|
||||
ins.size = readUint16();
|
||||
break;
|
||||
|
||||
case ByteCode::PushConstant:
|
||||
switch (ins.type) {
|
||||
case InstructionType::Int:
|
||||
ins.intValue = readInt32BE();
|
||||
ins.intValue = readInt32();
|
||||
break;
|
||||
case InstructionType::Float:
|
||||
ins.floatValue = readFloatBE();
|
||||
ins.floatValue = readFloat();
|
||||
break;
|
||||
case InstructionType::String: {
|
||||
uint16_t len = readUint16BE();
|
||||
uint16_t len = readUint16();
|
||||
ins.strValue = readFixedString(len);
|
||||
break;
|
||||
}
|
||||
case InstructionType::Object:
|
||||
ins.objectId = readInt32BE();
|
||||
ins.objectId = readInt32();
|
||||
break;
|
||||
default:
|
||||
throw runtime_error(str(boost::format("NCS: unsupported instruction type: %02x %02x") % static_cast<int>(ins.byteCode) % static_cast<int>(ins.type)));
|
||||
|
@ -86,89 +84,66 @@ void NcsFile::readInstruction(uint32_t &offset) {
|
|||
break;
|
||||
|
||||
case ByteCode::CallRoutine:
|
||||
ins.routine = readUint16BE();
|
||||
ins.routine = readUint16();
|
||||
ins.argCount = readByte();
|
||||
break;
|
||||
|
||||
case ByteCode::LogicalAnd:
|
||||
case ByteCode::LogicalOr:
|
||||
case ByteCode::InclusiveBitwiseOr:
|
||||
case ByteCode::ExclusiveBitwiseOr:
|
||||
case ByteCode::BitwiseAnd:
|
||||
break;
|
||||
|
||||
case ByteCode::Equal:
|
||||
case ByteCode::NotEqual:
|
||||
break;
|
||||
|
||||
case ByteCode::GreaterThanOrEqual:
|
||||
case ByteCode::GreaterThan:
|
||||
case ByteCode::LessThan:
|
||||
case ByteCode::LessThanOrEqual:
|
||||
break;
|
||||
|
||||
case ByteCode::ShiftLeft:
|
||||
case ByteCode::ShiftRight:
|
||||
case ByteCode::UnsignedShiftRight:
|
||||
break;
|
||||
|
||||
case ByteCode::Add:
|
||||
break;
|
||||
|
||||
case ByteCode::Subtract:
|
||||
break;
|
||||
|
||||
case ByteCode::Multiply:
|
||||
break;
|
||||
|
||||
case ByteCode::Divide:
|
||||
break;
|
||||
|
||||
case ByteCode::Mod:
|
||||
break;
|
||||
|
||||
case ByteCode::Negate:
|
||||
break;
|
||||
|
||||
case ByteCode::OnesComplement:
|
||||
break;
|
||||
|
||||
case ByteCode::AdjustSP:
|
||||
ins.stackOffset = readInt32BE();
|
||||
ins.stackOffset = readInt32();
|
||||
break;
|
||||
|
||||
case ByteCode::Jump:
|
||||
case ByteCode::JumpToSubroutine:
|
||||
case ByteCode::JumpIfZero:
|
||||
case ByteCode::JumpIfNonZero:
|
||||
ins.jumpOffset = offset + readInt32BE();
|
||||
break;
|
||||
|
||||
case ByteCode::Return:
|
||||
case ByteCode::SaveBP:
|
||||
case ByteCode::RestoreBP:
|
||||
case ByteCode::Noop:
|
||||
ins.jumpOffset = offset + readInt32();
|
||||
break;
|
||||
|
||||
case ByteCode::Destruct:
|
||||
ins.size = readUint16BE();
|
||||
ins.stackOffset = readInt16BE();
|
||||
ins.sizeNoDestroy = readUint16BE();
|
||||
break;
|
||||
|
||||
case ByteCode::LogicalNot:
|
||||
ins.size = readUint16();
|
||||
ins.stackOffset = readInt16();
|
||||
ins.sizeNoDestroy = readUint16();
|
||||
break;
|
||||
|
||||
case ByteCode::DecRelToSP:
|
||||
case ByteCode::IncRelToSP:
|
||||
case ByteCode::DecRelToBP:
|
||||
case ByteCode::IncRelToBP:
|
||||
ins.stackOffset = readInt32BE();
|
||||
ins.stackOffset = readInt32();
|
||||
break;
|
||||
|
||||
case ByteCode::StoreState:
|
||||
ins.size = readUint32BE();
|
||||
ins.sizeLocals = readUint32BE();
|
||||
ins.size = readUint32();
|
||||
ins.sizeLocals = readUint32();
|
||||
break;
|
||||
|
||||
case ByteCode::Reserve:
|
||||
case ByteCode::LogicalAnd:
|
||||
case ByteCode::LogicalOr:
|
||||
case ByteCode::InclusiveBitwiseOr:
|
||||
case ByteCode::ExclusiveBitwiseOr:
|
||||
case ByteCode::BitwiseAnd:
|
||||
case ByteCode::Equal:
|
||||
case ByteCode::NotEqual:
|
||||
case ByteCode::GreaterThanOrEqual:
|
||||
case ByteCode::GreaterThan:
|
||||
case ByteCode::LessThan:
|
||||
case ByteCode::LessThanOrEqual:
|
||||
case ByteCode::ShiftLeft:
|
||||
case ByteCode::ShiftRight:
|
||||
case ByteCode::UnsignedShiftRight:
|
||||
case ByteCode::Add:
|
||||
case ByteCode::Subtract:
|
||||
case ByteCode::Multiply:
|
||||
case ByteCode::Divide:
|
||||
case ByteCode::Mod:
|
||||
case ByteCode::Negate:
|
||||
case ByteCode::OnesComplement:
|
||||
case ByteCode::Return:
|
||||
case ByteCode::SaveBP:
|
||||
case ByteCode::RestoreBP:
|
||||
case ByteCode::Noop:
|
||||
case ByteCode::LogicalNot:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -35,6 +35,19 @@ StreamReader::StreamReader(const shared_ptr<istream> &stream, Endianess endianes
|
|||
}
|
||||
}
|
||||
|
||||
size_t StreamReader::tell() {
|
||||
return _stream->tellg();
|
||||
}
|
||||
|
||||
void StreamReader::seek(size_t pos) {
|
||||
_stream->clear();
|
||||
_stream->seekg(pos);
|
||||
}
|
||||
|
||||
void StreamReader::ignore(int count) {
|
||||
_stream->ignore(count);
|
||||
}
|
||||
|
||||
uint8_t StreamReader::getByte() {
|
||||
uint8_t val;
|
||||
_stream->read(reinterpret_cast<char *>(&val), 1);
|
||||
|
|
|
@ -30,6 +30,10 @@ class StreamReader {
|
|||
public:
|
||||
StreamReader(const std::shared_ptr<std::istream> &stream, Endianess endianess = Endianess::Little);
|
||||
|
||||
size_t tell();
|
||||
void seek(size_t pos);
|
||||
void ignore(int count);
|
||||
|
||||
uint8_t getByte();
|
||||
uint16_t getUint16();
|
||||
uint32_t getUint32();
|
||||
|
|
Loading…
Reference in a new issue