refactor: Make use of the StreamReader in the BinaryFile

This commit is contained in:
Vsevolod Kremianskii 2020-11-08 00:37:51 +07:00
parent a182063e2e
commit 0d9962dc50
6 changed files with 99 additions and 192 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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:

View file

@ -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);

View file

@ -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();