refactor: Streamline the BinaryFile class

This commit is contained in:
Vsevolod Kremianskii 2020-11-08 09:00:45 +07:00
parent 0d9962dc50
commit 04dc2a87bd
20 changed files with 170 additions and 175 deletions

View file

@ -33,7 +33,7 @@ WavFile::WavFile() : BinaryFile(0) {
}
void WavFile::doLoad() {
string sign(readFixedString(4));
string sign(readString(4));
if (sign == "\xff\xf3\x60\xc4") {
seek(0x1da);
} else if (sign != "RIFF") {
@ -41,7 +41,7 @@ void WavFile::doLoad() {
}
uint32_t chunkSize = readUint32();
string format(readFixedString(4));
string format(readString(4));
if (format != "WAVE") {
throw runtime_error("WAV: invalid chunk format: " + format);
}
@ -59,9 +59,9 @@ void WavFile::doLoad() {
}
bool WavFile::readChunkHeader(ChunkHeader &chunk) {
if (_in->eof()) return false;
if (_reader->eof()) return false;
string id(readFixedString(4));
string id(readString(4));
uint32_t size = readUint32();
chunk.id = move(id);
@ -95,9 +95,8 @@ void WavFile::loadFormat(ChunkHeader chunk) {
void WavFile::loadData(ChunkHeader chunk) {
if (chunk.size == 0) {
uint32_t pos = tell();
ByteArray data(_size - pos);
_in->read(&data[0], data.size());
size_t pos = tell();
ByteArray data(_reader->getArray<char>(_size - pos));
Mp3File mp3;
mp3.load(move(data));
@ -117,11 +116,13 @@ void WavFile::loadData(ChunkHeader chunk) {
}
void WavFile::loadPCM(uint32_t chunkSize) {
ByteArray data(_reader->getArray<char>(chunkSize));
AudioStream::Frame frame;
frame.format = getAudioFormat();
frame.sampleRate = _sampleRate;
frame.samples.resize(chunkSize);
_in->read(&frame.samples[0], chunkSize);
frame.samples = move(data);
_stream = make_shared<AudioStream>();
_stream->add(move(frame));
@ -142,8 +143,7 @@ static const int kIMAStepTable[] = {
};
void WavFile::loadIMAADPCM(uint32_t chunkSize) {
ByteArray chunk(chunkSize);
_in->read(&chunk[0], chunkSize);
ByteArray chunk(_reader->getArray<char>(chunkSize));
AudioStream::Frame frame;
frame.format = getAudioFormat();

View file

@ -52,14 +52,9 @@ void CurFile::loadData() {
int pixelCount = _width * _width;
int colorCount = _bitCount == 8 ? 256 : 16;
ByteArray palette(4 * colorCount);
_in->read(&palette[0], palette.size());
ByteArray xorData(pixelCount);
_in->read(&xorData[0], xorData.size());
ByteArray andData(pixelCount / 8);
_in->read(&andData[0], andData.size());
ByteArray palette(_reader->getArray<char>(4 * colorCount));
ByteArray xorData(_reader->getArray<char>(pixelCount));
ByteArray andData(_reader->getArray<char>(pixelCount / 8));
Texture::MipMap mipMap;
mipMap.width = _width;

View file

@ -78,9 +78,7 @@ void TgaFile::loadTexture() {
if (_imageType == ImageType::Grayscale) {
int size = _width * _height;
ByteArray buf(size);
_in->read(&buf[0], size);
ByteArray buf(_reader->getArray<char>(size));
char *pi = &mipMap.data[0];
for (int i = 0; i < size; ++i) {
@ -90,9 +88,9 @@ void TgaFile::loadTexture() {
pi[3] = static_cast<char>(0xff);
pi += 4;
}
} else {
_in->read(&mipMap.data[0], finalSize);
ByteArray data(_reader->getArray<char>(finalSize));
mipMap.data = move(data);
}
}

View file

@ -111,18 +111,15 @@ void TpcFile::loadTexture() {
getMipMapSize(j, mipMap.width, mipMap.height);
dataSize = getMipMapDataSize(mipMap.width, mipMap.height);
}
ByteArray &data = mipMap.data;
data.resize(dataSize);
_in->read(&data[0], dataSize);
ByteArray data(_reader->getArray<char>(dataSize));
mipMap.data = move(data);
}
}
uint32_t pos = tell();
size_t pos = tell();
if (pos < _size) {
ByteArray data(_size - pos);
_in->read(&data[0], data.size());
ByteArray data(_reader->getArray<char>(_size - pos));
TxiFile txi;
txi.load(wrap(data));

View file

@ -69,6 +69,7 @@ MdlFile::MdlFile(GameVersion version) : BinaryFile(kSignatureSize, kSignature),
void MdlFile::load(const shared_ptr<istream> &mdl, const shared_ptr<istream> &mdx) {
_mdx = mdx;
_mdxReader = make_unique<StreamReader>(mdx);
BinaryFile::load(mdl);
}
@ -81,7 +82,7 @@ void MdlFile::doLoad() {
ignore(8);
_name = readFixedString(32);
_name = readCString(32);
boost::to_lower(_name);
uint32_t rootNodeOffset = readUint32();
@ -102,7 +103,7 @@ void MdlFile::doLoad() {
float radius = readFloat();
float scale = readFloat();
string superModelName(readFixedString(32));
string superModelName(readCString(32));
boost::to_lower(superModelName);
ignore(16);
@ -132,7 +133,7 @@ void MdlFile::openMDX() {
throw runtime_error("MDL: MDX file not found: " + mdxPath.string());
}
_mdx.reset(new fs::ifstream(mdxPath, ios::binary));
_mdxReader = make_unique<StreamReader>(_mdx);
}
void MdlFile::readArrayDefinition(uint32_t &offset, uint32_t &count) {
@ -145,7 +146,7 @@ void MdlFile::readNodeNames(const vector<uint32_t> &offsets) {
map<string, int> nameHits;
for (uint32_t offset : offsets) {
string name(readString(kMdlDataOffset + offset));
string name(readCStringAt(kMdlDataOffset + offset));
boost::to_lower(name);
int hitCount = nameHits[name]++;
@ -158,7 +159,7 @@ void MdlFile::readNodeNames(const vector<uint32_t> &offsets) {
}
unique_ptr<ModelNode> MdlFile::readNode(uint32_t offset, ModelNode *parent) {
uint32_t pos = tell();
size_t pos = tell();
seek(offset);
uint16_t flags = readUint16();
@ -236,7 +237,7 @@ unique_ptr<ModelNode> MdlFile::readNode(uint32_t offset, ModelNode *parent) {
}
void MdlFile::readControllers(uint32_t keyCount, uint32_t keyOffset, const vector<float> &data, ModelNode &node) {
uint32_t pos = tell();
size_t pos = tell();
seek(kMdlDataOffset + keyOffset);
for (uint32_t i = 0; i < keyCount; ++i) {
@ -416,10 +417,10 @@ unique_ptr<ModelMesh> MdlFile::readMesh() {
uint32_t transparency = readUint32();
string diffuse(readFixedString(32));
string diffuse(readCString(32));
boost::to_lower(diffuse);
string lightmap(readFixedString(32));
string lightmap(readCString(32));
boost::to_lower(lightmap);
ignore(36);
@ -458,7 +459,7 @@ unique_ptr<ModelMesh> MdlFile::readMesh() {
ignore(4);
uint32_t endPos = tell();
size_t endPos = tell();
if (faceCount == 0) {
warn(boost::format("MDL: invalid face count: %d, model %s") % to_string(faceCount) % _name);
@ -478,8 +479,8 @@ unique_ptr<ModelMesh> MdlFile::readMesh() {
int valPerVert = mdxVertexSize / sizeof(float);
int vertValCount = valPerVert * vertexCount;
seek(*_mdx, mdxDataOffset);
vector<float> vertices(readArray<float>(*_mdx, vertValCount));
_mdxReader->seek(mdxDataOffset);
vector<float> vertices(_mdxReader->getArray<float>(vertValCount));
Mesh::VertexOffsets offsets;
offsets.vertexCoords = mdxVerticesOffset;
@ -557,7 +558,7 @@ unique_ptr<Animation> MdlFile::readAnimation(uint32_t offset) {
seek(kMdlDataOffset + offset);
ignore(8);
string name(readFixedString(32));
string name(readCString(32));
boost::to_lower(name);
uint32_t rootNodeOffset = readUint32();

View file

@ -36,6 +36,7 @@ public:
private:
resource::GameVersion _version { resource::GameVersion::KotOR };
std::shared_ptr<std::istream> _mdx;
std::unique_ptr<StreamReader> _mdxReader;
std::string _name;
int _nodeIndex { 0 };
std::vector<std::string> _nodeNames;

View file

@ -19,6 +19,7 @@
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include "../system/log.h"
@ -136,7 +137,7 @@ void TwoDaFile::loadHeaders() {
}
bool TwoDaFile::readToken(string &token) {
uint32_t pos = tell();
size_t pos = tell();
char buf[256];
streamsize chRead = _in->rdbuf()->sgetn(buf, sizeof(buf));
@ -155,7 +156,7 @@ bool TwoDaFile::readToken(string &token) {
}
}
throw runtime_error("2DA: token not terminated");
throw runtime_error("2DA token not terminated");
}
void TwoDaFile::loadLabels() {
@ -177,7 +178,7 @@ void TwoDaFile::loadRows() {
}
uint16_t dataSize = readUint16();
uint32_t pos = tell();
size_t pos = tell();
for (int i = 0; i < _rowCount; ++i) {
TwoDaRow row;
@ -185,9 +186,9 @@ void TwoDaFile::loadRows() {
for (int j = 0; j < columnCount; ++j) {
const string &name = _table->_headers[j];
int cellIdx = i * columnCount + j;
uint32_t off = pos + offsets[cellIdx];
size_t off = pos + offsets[cellIdx];
row.add(name, readString(off));
row.add(name, readCStringAt(off));
}
_table->_rows.push_back(row);

View file

@ -66,6 +66,7 @@ private:
class TwoDaFile : public BinaryFile {
public:
TwoDaFile();
const std::shared_ptr<TwoDaTable> &table() const;
private:

View file

@ -25,26 +25,6 @@ namespace reone {
namespace resource {
vector<char> BinaryFile::readArray(istream &in, int n) {
if (n == 0) {
return ByteArray();
}
ByteArray arr(n);
in.read(&arr[0], n);
return move(arr);
}
vector<char> BinaryFile::readArray(istream &in, uint32_t off, int n) {
streampos pos = in.tellg();
in.seekg(off);
ByteArray arr(readArray<char>(in, n));
in.seekg(pos);
return move(arr);
}
BinaryFile::BinaryFile(int signSize, const char *sign) : _signSize(signSize) {
if (!sign) return;
@ -96,67 +76,63 @@ void BinaryFile::load(const fs::path &path) {
load();
}
uint32_t BinaryFile::tell() const {
size_t BinaryFile::tell() const {
return _reader->tell();
}
void BinaryFile::ignore(int size) {
_reader->ignore(size);
void BinaryFile::seek(size_t pos) {
_reader->seek(pos);
}
void BinaryFile::ignore(int count) {
_reader->ignore(count);
}
uint8_t BinaryFile::readByte() {
return _reader->getByte();
}
int16_t BinaryFile::readInt16() {
return _reader->getInt16();
}
uint16_t BinaryFile::readUint16() {
return _reader->getUint16();
}
int32_t BinaryFile::readInt32() {
return _reader->getInt32();
}
uint32_t BinaryFile::readUint32() {
return _reader->getUint32();
}
int64_t BinaryFile::readInt64() {
return _reader->getInt64();
}
uint64_t BinaryFile::readUint64() {
return _reader->getUint64();
}
int16_t BinaryFile::readInt16() {
return _reader->getInt16();
}
int32_t BinaryFile::readInt32() {
return _reader->getInt32();
}
float BinaryFile::readFloat() {
return _reader->getFloat();
}
double BinaryFile::readDouble() {
return _reader->getDouble();
}
string BinaryFile::readFixedString(int size) {
string result(_reader->getString(size));
string BinaryFile::readCString(int len) {
string result(_reader->getString(len));
result.erase(find(result.begin(), result.end(), '\0'), result.end());
return move(result);
}
string BinaryFile::readFixedString(uint32_t off, int size) {
string BinaryFile::readCString(size_t off, int len) {
size_t pos = _reader->tell();
_reader->seek(off);
string result(readFixedString(size));
string result(readCString(len));
_reader->seek(pos);
return move(result);
}
string BinaryFile::readString(uint32_t off) {
string BinaryFile::readCStringAt(size_t off) {
size_t pos = _reader->tell();
_reader->seek(off);
@ -166,11 +142,15 @@ string BinaryFile::readString(uint32_t off) {
return move(result);
}
string BinaryFile::readString(uint32_t off, int size) {
string BinaryFile::readString(int len) {
return _reader->getString(len);
}
string BinaryFile::readString(size_t off, int len) {
size_t pos = _reader->tell();
_reader->seek(off);
string result(_reader->getString(size));
string result(_reader->getString(len));
_reader->seek(pos);
return move(result);

View file

@ -17,6 +17,11 @@
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include "../system/streamreader.h"
@ -41,68 +46,41 @@ protected:
std::unique_ptr<StreamReader> _reader;
size_t _size { 0 };
template <typename T>
static void seek(std::istream &in, T off) {
in.seekg(off);
}
template <typename T>
static std::vector<T> readArray(std::istream &in, int n) {
if (n == 0) return std::vector<T>();
std::vector<T> arr(n);
in.read(reinterpret_cast<char *>(&arr[0]), n * sizeof(T));
return std::move(arr);
}
static inline std::vector<char> readArray(std::istream &in, int n);
template <typename T>
static std::vector<T> readArray(std::istream &in, uint32_t off, int n) {
std::streampos pos = in.tellg();
in.seekg(off);
std::vector<T> arr(readArray<T>(in, n));
in.seekg(pos);
return std::move(arr);
}
static inline std::vector<char> readArray(std::istream &in, uint32_t off, int n);
BinaryFile(int signSize, const char *sign = 0);
virtual void doLoad() = 0;
uint32_t tell() const;
void ignore(int size);
size_t tell() const;
void seek(size_t off);
void ignore(int count);
uint8_t readByte();
int16_t readInt16();
uint16_t readUint16();
int32_t readInt32();
uint32_t readUint32();
int64_t readInt64();
uint64_t readUint64();
int16_t readInt16();
int32_t readInt32();
float readFloat();
double readDouble();
std::string readFixedString(int size);
std::string readFixedString(uint32_t off, int size);
std::string readString(uint32_t off);
std::string readString(uint32_t off, int size);
std::string readCString(int len);
std::string readCString(size_t off, int len);
std::string readCStringAt(size_t off);
std::string readString(int len);
std::string readString(size_t off, int len);
template <typename T>
void seek(T off) {
_in->seekg(off);
template <class T>
std::vector<T> readArray(int count) {
return _reader->getArray<T>(count);
}
template <typename T>
std::vector<T> readArray(int n) {
return readArray<T>(*_in, n);
}
template <class T>
std::vector<T> readArray(uint32_t off, int count) {
size_t pos = _reader->tell();
_reader->seek(off);
template <typename T>
std::vector<T> readArray(uint32_t off, int n) {
return readArray<T>(*_in, off, n);
std::vector<T> result(_reader->getArray<T>(count));
_reader->seek(pos);
return std::move(result);
}
private:

View file

@ -53,12 +53,11 @@ void ErfFile::checkSignature() {
if (_size < kSignatureSize) {
throw runtime_error("Invalid binary file size");
}
char buf[kSignatureSize];
_in->read(buf, kSignatureSize);
string sign(_reader->getString(kSignatureSize));
bool erf = strncmp(buf, kSignatureErf, kSignatureSize) == 0;
bool erf = strncmp(&sign[0], kSignatureErf, kSignatureSize) == 0;
if (!erf) {
bool mod = strncmp(buf, kSignatureMod, kSignatureSize) == 0;
bool mod = strncmp(&sign[0], kSignatureMod, kSignatureSize) == 0;
if (!mod) {
throw runtime_error("Invalid ERF file signature");
}
@ -75,7 +74,7 @@ void ErfFile::loadKeys() {
}
ErfFile::Key ErfFile::readKey() {
string resRef(readFixedString(16));
string resRef(readCString(16));
uint32_t resId = readUint32();
uint16_t resType = readUint16();
ignore(2);

View file

@ -304,7 +304,7 @@ GffField GffFile::readField(int idx) {
string GffFile::readLabel(int idx) {
uint32_t off = _labelOffset + 16 * idx;
return readFixedString(off, 16);
return readCString(off, 16);
}
vector<uint32_t> GffFile::readFieldIndices(uint32_t off, int count) {
@ -312,7 +312,7 @@ vector<uint32_t> GffFile::readFieldIndices(uint32_t off, int count) {
}
uint64_t GffFile::readQWordFieldData(uint32_t off) {
uint32_t pos = tell();
size_t pos = tell();
seek(_fieldDataOffset + off);
uint64_t val = readUint64();
seek(pos);
@ -321,29 +321,29 @@ uint64_t GffFile::readQWordFieldData(uint32_t off) {
}
string GffFile::readStringFieldData(uint32_t off) {
uint32_t pos = tell();
size_t pos = tell();
seek(_fieldDataOffset + off);
uint32_t size = readUint32();
string s(readFixedString(size));
string s(readCString(size));
seek(pos);
return move(s);
}
string GffFile::readResRefFieldData(uint32_t off) {
uint32_t pos = tell();
size_t pos = tell();
seek(_fieldDataOffset + off);
uint8_t size = readByte();
string s(readFixedString(size));
string s(readCString(size));
seek(pos);
return move(s);
}
GffFile::LocString GffFile::readCExoLocStringFieldData(uint32_t off) {
uint32_t pos = tell();
size_t pos = tell();
seek(_fieldDataOffset + off);
uint32_t size = readUint32();
@ -356,7 +356,7 @@ GffFile::LocString GffFile::readCExoLocStringFieldData(uint32_t off) {
if (count > 0) {
int32_t type = readInt32();
uint32_t ssSize = readUint32();
loc.subString = readFixedString(ssSize);
loc.subString = readCString(ssSize);
}
seek(pos);
@ -365,7 +365,7 @@ GffFile::LocString GffFile::readCExoLocStringFieldData(uint32_t off) {
}
int32_t GffFile::readStrRefFieldData(uint32_t off) {
uint32_t pos = tell();
size_t pos = tell();
seek(_fieldDataOffset + off);
uint32_t size = readUint32();
@ -377,7 +377,7 @@ int32_t GffFile::readStrRefFieldData(uint32_t off) {
}
ByteArray GffFile::readByteArrayFieldData(uint32_t off) {
uint32_t pos = tell();
size_t pos = tell();
seek(_fieldDataOffset + off);
uint32_t size = readUint32();
@ -392,8 +392,8 @@ ByteArray GffFile::readByteArrayFieldData(uint32_t off, int size) {
}
vector<uint32_t> GffFile::readList(uint32_t off) {
streampos pos = _in->tellg();
seek(_listIndicesOffset + off);
size_t pos = tell();
seek(static_cast<size_t>(_listIndicesOffset) + off);
uint32_t count = readUint32();
vector<uint32_t> arr(readArray<uint32_t>(count));

View file

@ -60,7 +60,7 @@ KeyFile::FileEntry KeyFile::readFileEntry() {
FileEntry entry;
entry.fileSize = fileSize;
entry.filename = readFixedString(filenameOffset, filenameSize);
entry.filename = readCString(filenameOffset, filenameSize);
return move(entry);
}
@ -75,7 +75,7 @@ void KeyFile::loadKeys() {
}
KeyFile::KeyEntry KeyFile::readKeyEntry() {
string resRef(readFixedString(16));
string resRef(readCString(16));
uint16_t resType = readUint16();
uint32_t resId = readUint32();

View file

@ -84,7 +84,7 @@ void PEFile::loadOptionalHeader() {
}
void PEFile::loadSection() {
string name(readFixedString(8));
string name(readCString(8));
ignore(4);
@ -129,7 +129,7 @@ void PEFile::loadResourceDirEntry(const Section &section, int level) {
uint32_t sibling = readUint32();
bool siblingDir = (sibling & kSiblingMaskDir) != 0;
uint32_t pos = tell();
size_t pos = tell();
uint32_t offSibling = section.offset + (sibling & 0x7fffffff);
seek(offSibling);

View file

@ -52,7 +52,7 @@ void RimFile::loadResources() {
}
RimFile::Resource RimFile::readResource() {
string resRef(readFixedString(16));
string resRef(readCString(16));
uint16_t type = readUint16();
ignore(4 + 2);
uint32_t offset = readUint32();

View file

@ -57,7 +57,7 @@ void TlkFile::loadStrings() {
for (uint32_t i = 0; i < _stringCount; ++i) {
uint32_t flags = readUint32();
string soundResRef(readFixedString(16));
string soundResRef(readCString(16));
boost::to_lower(soundResRef);
ignore(8);

View file

@ -36,20 +36,20 @@ void NcsFile::doLoad() {
_program = make_unique<ScriptProgram>(_resRef);
_program->_length = length;
uint32_t off = tell();
size_t off = tell();
while (off < length) {
readInstruction(off);
}
}
void NcsFile::readInstruction(uint32_t &offset) {
void NcsFile::readInstruction(size_t &offset) {
seek(offset);
uint8_t byteCode = readByte();
uint8_t type = readByte();
Instruction ins;
ins.offset = offset;
ins.offset = static_cast<uint32_t>(offset);
ins.byteCode = static_cast<ByteCode>(byteCode);
ins.type = static_cast<InstructionType>(type);
@ -72,7 +72,7 @@ void NcsFile::readInstruction(uint32_t &offset) {
break;
case InstructionType::String: {
uint16_t len = readUint16();
ins.strValue = readFixedString(len);
ins.strValue = readCString(len);
break;
}
case InstructionType::Object:
@ -96,7 +96,7 @@ void NcsFile::readInstruction(uint32_t &offset) {
case ByteCode::JumpToSubroutine:
case ByteCode::JumpIfZero:
case ByteCode::JumpIfNonZero:
ins.jumpOffset = offset + readInt32();
ins.jumpOffset = static_cast<uint32_t>(offset + readInt32());
break;
case ByteCode::Destruct:
@ -150,10 +150,10 @@ void NcsFile::readInstruction(uint32_t &offset) {
throw runtime_error(str(boost::format("NCS: unsupported byte code: %02x") % static_cast<int>(ins.byteCode)));
}
uint32_t pos = tell();
ins.nextOffset = pos;
size_t pos = tell();
ins.nextOffset = static_cast<uint32_t>(pos);
_program->_instructions.insert(make_pair(offset, move(ins)));
_program->_instructions.insert(make_pair(static_cast<uint32_t>(offset), move(ins)));
offset = pos;
}

View file

@ -45,7 +45,7 @@ private:
std::string _resRef;
std::shared_ptr<ScriptProgram> _program;
void readInstruction(uint32_t &offset);
void readInstruction(size_t &offset);
};
} // namespace script

View file

@ -128,4 +128,42 @@ string StreamReader::getString(int len) {
return move(val);
}
bool StreamReader::eof() const {
return _stream->eof();
}
template <>
vector<char> StreamReader::getArray(int count) {
vector<char> result(count);
_stream->read(&result[0], count);
return move(result);
}
template <>
vector<uint16_t> StreamReader::getArray(int count) {
vector<uint16_t> result(count);
for (int i = 0; i < count; ++i) {
result[i] = getUint16();
}
return move(result);
}
template <>
vector<uint32_t> StreamReader::getArray(int count) {
vector<uint32_t> result(count);
for (int i = 0; i < count; ++i) {
result[i] = getUint32();
}
return move(result);
}
template <>
vector<float> StreamReader::getArray(int count) {
vector<float> result(count);
for (int i = 0; i < count; ++i) {
result[i] = getFloat();
}
return move(result);
}
} // namespace reone

View file

@ -21,6 +21,7 @@
#include <istream>
#include <memory>
#include <string>
#include <vector>
#include "types.h"
@ -46,6 +47,11 @@ public:
std::string getCString();
std::string getString(int len);
bool eof() const;
template <class T>
std::vector<T> getArray(int count);
private:
std::shared_ptr<std::istream> _stream;
Endianess _endianess;