diff --git a/IffFile.cc b/IffFile.cc index 490b2b8..f939eac 100644 --- a/IffFile.cc +++ b/IffFile.cc @@ -9,13 +9,13 @@ struct ChunkHeader { uint32_t length; }; -IffFile::IffFile(uint8_t const* base, size_t length) - : base_(base), length_(length) +IffFile::IffFile(Resource const& res) + : res_(res) { size_t pos = 0; - while (pos < length) { - roots_.push_back(parseObject(base+pos, length-pos)); - pos += roots_.back()->getSize() + 8; + while (pos < res_.size()) { + roots_.push_back(parseObject(res_.data()+pos, res_.size()-pos)); + pos += roots_.back()->size() + 8; } } @@ -27,7 +27,7 @@ static void _printStructure(IffFile::Object const& obj, unsigned level) { for (unsigned i = 0;i < level;++i) putchar('\t'); - printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.getSize(), obj.getSize()); + printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.size(), obj.size()); if (obj.isForm()) { auto& form = dynamic_cast(obj); @@ -129,7 +129,7 @@ IffFile::Form::Form(std::string type, uint8_t const* base, size_t length) size_t pos = 4; while (pos+8 < length) { children_.push_back(parseObject(base+pos, length-pos)); - pos += 8 + children_.back()->getSize(); + pos += 8 + children_.back()->size(); if (pos%2 != 0) ++pos; diff --git a/IffFile.hh b/IffFile.hh index 4a70da7..b21bbb6 100644 --- a/IffFile.hh +++ b/IffFile.hh @@ -7,9 +7,11 @@ #include #include +#include "Resource.hh" + class IffFile { public: - IffFile(uint8_t const* base, size_t length); + IffFile(Resource const& res); ~IffFile(); @@ -109,12 +111,12 @@ public: std::vector >::const_iterator implIt_; }; - class Object { + class Object : public Resource { public: Object(std::string type, uint8_t const* base, size_t length); Object(Object const& copy) = delete; - virtual ~Object() { + ~Object() override { } std::string const& getType() const { @@ -125,10 +127,14 @@ public: return (typeid(*this) == typeid(Form)); } - size_t getSize() const { + size_t size() const override { return length_; } + uint8_t const* data() const override { + return base_; + } + uint8_t const* begin() const { return base_; } @@ -138,6 +144,10 @@ public: } operator std::string() const; + + operator bool() const override { + return true; + } protected: uint8_t const* base_; @@ -188,8 +198,7 @@ public: private: static std::unique_ptr parseObject(uint8_t const* base, size_t length); - uint8_t const* base_; - const size_t length_; + Resource const& res_; std::vector > roots_; }; diff --git a/MveDecoder.cc b/MveDecoder.cc index c314a02..8aec29c 100644 --- a/MveDecoder.cc +++ b/MveDecoder.cc @@ -8,8 +8,8 @@ #include "decompress.hh" #include "MveDecoder.hh" -MveDecoder::MveDecoder(uint8_t const* base, size_t length) - : iff_(base, length), width_(320), height_(165) +MveDecoder::MveDecoder(Resource const& res) + : iff_(res), width_(320), height_(165) { //iff_.printStructure(); @@ -26,7 +26,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length) // Parse _PC_ chunk auto& PC = *it++; if ((PC.getType() != "_PC_") || - (PC.getSize() != 12)) + (PC.size() != 12)) throw FormatException{"_PC_ chunk missing or wrong size"}; const uint32_t PC_PALTcount = readU32LE(PC.begin()+8); @@ -37,7 +37,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length) // // Parse SOND chunk // auto& SOND = *it++; // if ((SOND.getType() != "SOND") || - // (SOND.getSize() != 4)) + // (SOND.size() != 4)) // throw FormatException{"SOND chunk missing or wrong size"}; // const uint32_t SONDc = readU32LE(SOND.begin()); @@ -53,7 +53,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length) for (;it != rootForm.childrenEnd();++it) { if (it->getType() == "SIZE") { - if (it->getSize() != 8) + if (it->size() != 8) throw FormatException{"Unexpected SIZE size"}; width_ = readU32LE(it->begin()); @@ -61,7 +61,7 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length) } else if (it->getType() == "PALT") { if (curPALT > PC_PALTcount) throw FormatException{"Number of PALT chunks exceeds amount specified in _PC_"}; - if (it->getSize() != 768) + if (it->size() != 768) throw FormatException{"Unexpected PALT size"}; palts_.emplace_back(); @@ -95,11 +95,11 @@ MveDecoder::MveDecoder(uint8_t const* base, size_t length) throw FormatException{"INDX after SHOT"}; haveIndex = true; - for(unsigned i = 0;i < it->getSize()/4;++i) + for(unsigned i = 0;i < it->size()/4;++i) branches.push_back(readU32LE(it->begin()+i*4)); branches_.resize(branches.size()); } else if (it->getType() == "BRCH") { - size_t ofs = it->begin()-base-8; + size_t ofs = it->begin()-res.data()-8; auto idxIt = std::find(branches.begin(), branches.end(), ofs); if (idxIt == branches.end()) throw FormatException{"Could not resolve branch " + std::to_string(ofs)}; @@ -276,13 +276,13 @@ unsigned MveDecoder::Movie::getHeight() const void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) { // Parse header - if (vga.getSize() < 8) + if (vga.size() < 8) throw FormatException{"VGA chunk smaller than VGA header"}; std::array segOfs; for(unsigned i = 0;i < segOfs.size();++i) { segOfs[i] = readU16LE(vga.begin()+i*2); - if (segOfs[i] >= vga.getSize()) + if (segOfs[i] >= vga.size()) throw FormatException{"Segment offset exceeds chunk"}; } @@ -291,7 +291,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) ((segOfs[1] && (segOfs[1] - segOfs[0]) < 45)) || ((segOfs[2] && (segOfs[2] - segOfs[0]) < 45)) || ((segOfs[3] && (segOfs[3] - segOfs[0]) < 45)) || - (vga.getSize() - segOfs[0] < 45)) + (vga.size() - segOfs[0] < 45)) throw FormatException{"Segment 1 too small"}; commandBuf_.clear(); @@ -301,7 +301,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) size_t pixelCount = 0; if (segOfs[3]) { - pixelCount = parsePixels_(vga.begin()+segOfs[3], vga.getSize()-segOfs[3], + pixelCount = parsePixels_(vga.begin()+segOfs[3], vga.size()-segOfs[3], pixelBuf_.data(), pixelBuf_.size()); maxPixel_ = std::max(maxPixel_, pixelCount); } @@ -309,7 +309,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) #ifdef VIDDEBUG_ printf("%lu commands, %lu pixel data, %u mvecs, %lu size data\n", commands.size(), pixels.size(), (segOfs[2]?(segOfs[3]-segOfs[2]):0), - segOfs[2]?(segOfs[2]-segOfs[1]):(segOfs[3]?(segOfs[3]-segOfs[1]):(vga.getSize()-segOfs[1]))); + segOfs[2]?(segOfs[2]-segOfs[1]):(segOfs[3]?(segOfs[3]-segOfs[1]):(vga.size()-segOfs[1]))); #endif // Interpret command stream to render frame @@ -352,7 +352,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) if (!segOfs[1] || (segOfs[2] && (segOfs[1]+seg2Idx >= segOfs[2])) || (segOfs[3] && (segOfs[1]+seg2Idx >= segOfs[3])) || - (segOfs[1]+seg2Idx >= vga.getSize())) + (segOfs[1]+seg2Idx >= vga.size())) throw FormatException{"Segment 2 overrun"}; size = vga.begin()[segOfs[1]+seg2Idx++]&0xff; break; @@ -361,7 +361,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) if (!segOfs[1] || (segOfs[2] && (segOfs[1]+seg2Idx+1 >= segOfs[2])) || (segOfs[3] && (segOfs[1]+seg2Idx >= segOfs[3])) || - (segOfs[1]+seg2Idx+1 >= vga.getSize())) + (segOfs[1]+seg2Idx+1 >= vga.size())) throw FormatException{"Segment 2 overrun"}; size = readU16BE(vga.begin()+segOfs[1]+seg2Idx); seg2Idx += 2; @@ -371,7 +371,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) if (!segOfs[1] || (segOfs[2] && (segOfs[1]+seg2Idx+2 >= segOfs[2])) || (segOfs[3] && (segOfs[1]+seg2Idx >= segOfs[3])) || - (segOfs[1]+seg2Idx+2 >= vga.getSize())) + (segOfs[1]+seg2Idx+2 >= vga.size())) throw FormatException{"Segment 2 overrun"}; size = readU24BE(vga.begin()+segOfs[1]+seg2Idx); seg2Idx += 3; @@ -410,7 +410,7 @@ void MveDecoder::Movie::parseVGA(IffFile::Object const& vga) #endif if (!segOfs[2] || (segOfs[3] && (segOfs[2]+seg3Idx > segOfs[3])) || - (segOfs[2]+seg3Idx > vga.getSize())) + (segOfs[2]+seg3Idx > vga.size())) throw FormatException{"Segment 3 overrun"}; const uint8_t mpos = vga.begin()[segOfs[2]+seg3Idx++]; @@ -467,7 +467,7 @@ void audioCB_(void* userdata, uint8_t *buf, int len) } while ((len > 0) && cbdata->cur) { - if (cbdata->pos >= (*cbdata->aCur)->getSize()) { + if (cbdata->pos >= (*cbdata->aCur)->size()) { cbdata->pos = 0; ++cbdata->aCur; if (cbdata->aCur == cbdata->cur->AUDIs.end()) { @@ -484,8 +484,8 @@ void audioCB_(void* userdata, uint8_t *buf, int len) auto& aCur = *cbdata->aCur; size_t toCopy = len; - if (cbdata->pos+toCopy > aCur->getSize()) - toCopy = aCur->getSize()-cbdata->pos; + if (cbdata->pos+toCopy > aCur->size()) + toCopy = aCur->size()-cbdata->pos; std::copy(aCur->begin()+cbdata->pos, aCur->begin()+cbdata->pos+toCopy, buf); len -= toCopy; diff --git a/MveDecoder.hh b/MveDecoder.hh index 286d422..d3d3aa3 100644 --- a/MveDecoder.hh +++ b/MveDecoder.hh @@ -6,9 +6,11 @@ #include "IffFile.hh" +class Resource; + class MveDecoder { public: - MveDecoder(uint8_t const* base, size_t length); + MveDecoder(Resource const& res); size_t numBranches() const { return branches_.size(); diff --git a/ObjDecoder.cc b/ObjDecoder.cc index 0ea0c76..d3358a3 100644 --- a/ObjDecoder.cc +++ b/ObjDecoder.cc @@ -4,8 +4,8 @@ #include "exceptions.hh" #include "util.hh" -ObjDecoder::ObjDecoder(uint8_t const* base, size_t length) - : iff_(base, length) +ObjDecoder::ObjDecoder(Resource const& res) + : iff_(res) { auto& root = iff_.getRoot(); if (!root.isForm()) @@ -17,7 +17,7 @@ ObjDecoder::ObjDecoder(uint8_t const* base, size_t length) for (auto realIt = rootForm.childrenBegin();realIt != rootForm.childrenEnd();++realIt) { if (realIt->getType() == "INFO") { - name_ = *realIt; + name_ = static_cast(*realIt); printf("Name: \"%s\"\n", name_.c_str()); } else if (realIt->isForm()) { auto& itForm = dynamic_cast(*realIt); @@ -79,9 +79,9 @@ void ObjDecoder::parsePOLY_(IffFile::Form const& form) for (auto it = form.childrenBegin();it != form.childrenEnd();++it) { if (it->getType() == "INFO") { } else if (it->getType() == "VERT") { - if (it->getSize()%12 != 0) + if (it->size()%12 != 0) throw FormatException{"Unexpected VERT size"}; - for (size_t i = 0;i < it->getSize();i+=12) { + for (size_t i = 0;i < it->size();i+=12) { std::array vertex; for (size_t j = 0;j < 3;++j) vertex[j] = readU32LE(it->begin()+i+j*4); @@ -137,10 +137,10 @@ void ObjDecoder::parseTRIS_(IffFile::Form const& form) assert(face && maps); - if (face->getSize()%8 != 0) + if (face->size()%8 != 0) throw FormatException{"Unexpected FACE size"}; - auto numTriangles = face->getSize()/8; - if (maps->getSize() != numTriangles*16) + auto numTriangles = face->size()/8; + if (maps->size() != numTriangles*16) printf("WARNING: Unexpected MAPS size\n"); // throw FormatException{"Unexpected MAPS size"}; @@ -185,10 +185,10 @@ void ObjDecoder::parseQUAD_(IffFile::Form const& form) assert(face && maps); - if (face->getSize()%10 != 0) + if (face->size()%10 != 0) throw FormatException{"Unexpected FACE size"}; - auto numQuads = face->getSize()/10; - if (maps->getSize() != numQuads*20) + auto numQuads = face->size()/10; + if (maps->size() != numQuads*20) printf("WARNING: Unexpected MAPS size\n"); //throw FormatException{"Unexpected MAPS size"}; @@ -225,12 +225,12 @@ void ObjDecoder::parseDETA_(IffFile::Form const& form) if (std::stoi(it->getType().substr(3)) != lvl) throw FormatException{"Unexpected detail level"}; - if (it->getSize() < 4) + if (it->size() < 4) throw FormatException{"DETA child too small"}; // uint32_t unkown = readU32LE(it->begin()); detailLevels_.emplace_back(); - for (size_t pos = 4;pos < it->getSize()-1;pos += 2) + for (size_t pos = 4;pos < it->size()-1;pos += 2) detailLevels_.back().push_back(readU16LE(it->begin()+pos)); printf("LVL %u: %lu entries\n", lvl, detailLevels_.back().size()); @@ -250,7 +250,7 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form) auto& info = *it++; if (info.getType() != "INFO") throw FormatException{"Missing INFO in TXMS"}; - if (info.getSize() != 4) + if (info.size() != 4) throw FormatException{"Unexpected INFO size in TXMS"}; uint16_t numTXMP, numTXMA; @@ -263,7 +263,7 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form) texAnims_.reserve(numTXMA); for (;it != form.childrenEnd();++it) { if (it->getType() == "TXMP") { - if (it->getSize() < 12u) + if (it->size() < 12u) throw FormatException{"TXMP smaller than header"}; Texture tex; @@ -277,12 +277,12 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form) tex.height = readU16LE(it->begin()+10); printf("TXMP size %hux%hu\n", tex.width, tex.height); - if (it->getSize() < 12u+tex.width*tex.height) + if (it->size() < 12u+tex.width*tex.height) throw FormatException{"TXMP too small for pixel data"}; tex.pixels = std::vector(it->begin()+12, it->begin()+12+tex.width*tex.height); textures_.emplace_back(std::move(tex)); } else if (it->getType() == "TXMA") { - if (it->getSize() < 14u) + if (it->size() < 14u) throw FormatException{"TXMA smaller than header"}; TextureAnimation tex; @@ -297,7 +297,7 @@ void ObjDecoder::parseTXMS_(IffFile::Form const& form) tex.frames = readU16LE(it->begin()+12); printf("TXMA size %hux%hu, %hu frames\n", tex.width, tex.height, tex.frames); - if (it->getSize() < 14u+tex.width*tex.height*tex.frames) + if (it->size() < 14u+tex.width*tex.height*tex.frames) throw FormatException{"TXMA too small for pixel data"}; tex.pixels.reserve(tex.frames); diff --git a/ObjDecoder.hh b/ObjDecoder.hh index 5e2a67c..bfb4625 100644 --- a/ObjDecoder.hh +++ b/ObjDecoder.hh @@ -8,9 +8,11 @@ #include "IffFile.hh" +class Resource; + class ObjDecoder { public: - ObjDecoder(uint8_t const* base, size_t length); + ObjDecoder(Resource const& res); using Vertex = std::array; using Vertices = std::vector; diff --git a/PaletteDecoder.cc b/PaletteDecoder.cc index 2d91a57..9dea55f 100644 --- a/PaletteDecoder.cc +++ b/PaletteDecoder.cc @@ -3,8 +3,8 @@ #include "PaletteDecoder.hh" #include "exceptions.hh" -PaletteDecoder::PaletteDecoder(uint8_t const* base, size_t length) - : iff_(base, length) +PaletteDecoder::PaletteDecoder(Resource const& res) + : iff_(res) { auto& root = iff_.getRoot(); if (!root.isForm()) @@ -20,6 +20,21 @@ PaletteDecoder::PaletteDecoder(uint8_t const* base, size_t length) std::transform(paltIt->begin()+4, paltIt->begin()+772, palette_.begin(), [](const char& in) -> uint8_t {return (in << 2) | ((in >> 6)&0x3);}); + uint8_t min = 0xff, max = 0; + for (auto it = paltIt->begin()+4;it != paltIt->end();++it) { + if (*it == 0xff) + continue; + min = std::min(min, *it); + max = std::max(max, *it); + } + + printf("palt value range %hhu..%hhu\n", min, max); + } else if (paltIt->getType() == "BLWH") { + auto dstIt = palette_.begin(); + for (auto it = paltIt->begin()+4;it != paltIt->end();++it) { + *dstIt = *dstIt * ((*it << 2) | ((*it >> 6)&0x3)) / 255u; + ++dstIt; + } } } } diff --git a/PaletteDecoder.hh b/PaletteDecoder.hh index 88a0b71..f99cb1f 100644 --- a/PaletteDecoder.hh +++ b/PaletteDecoder.hh @@ -8,7 +8,7 @@ class PaletteDecoder { public: - PaletteDecoder(uint8_t const* base, size_t length); + PaletteDecoder(Resource const& res); using Palette = std::array; diff --git a/Resource.hh b/Resource.hh new file mode 100644 index 0000000..f8ab693 --- /dev/null +++ b/Resource.hh @@ -0,0 +1,18 @@ +#ifndef WC3RE_RESOURCE_HH__ +#define WC3RE_RESOURCE_HH__ + +// Interface for any memory-resident resource +// For example mmap'd data file, TRE object, IFF Object, ... + +class Resource { +public: + virtual ~Resource() {} + + virtual uint8_t const* data() const = 0; + virtual size_t size() const = 0; + + virtual operator bool() const = 0; +}; + + +#endif diff --git a/TreFile.hh b/TreFile.hh index ce886e2..400350e 100644 --- a/TreFile.hh +++ b/TreFile.hh @@ -8,6 +8,8 @@ #include #include +#include "Resource.hh" + class TreFile { public: TreFile(uint8_t const* base, size_t length); @@ -27,7 +29,7 @@ public: 'path' */ static uint32_t calcCRC(std::string const& path); - class Object { + class Object : public Resource { public: Object() : base_(nullptr), length_(0) { } @@ -50,19 +52,22 @@ public: move.length_ = 0; return *this; } + + ~Object() override { + } - uint8_t const* data() const { + uint8_t const* data() const override { if (data_) return data_->data(); else return base_; } - size_t size() const { + size_t size() const override { return length_; } - operator bool() const { + operator bool() const override { return data_ || base_; } diff --git a/iffexplore.cc b/iffexplore.cc index 24b6656..d8547b2 100644 --- a/iffexplore.cc +++ b/iffexplore.cc @@ -10,13 +10,13 @@ #include "util.hh" #include "IffFile.hh" -void blobDump(IffFile::Object const& obj, std::string const& filename) +void blobDump(Resource const& obj, std::string const& filename) { FILEUPtr file{fopen(filename.c_str(), "wb")}; if (!file) throw POSIXException{errno, "Could not open file: " + filename}; - if (fwrite(obj.begin(), obj.getSize(), 1, file.get()) != 1) + if (fwrite(obj.data(), obj.size(), 1, file.get()) != 1) throw POSIXException{errno, "Could not write"}; } @@ -25,7 +25,7 @@ void iffDumper(IffFile::Object const& obj, bool dumpBlobs, std::string dumpPath, { for (unsigned i = 0;i < level;++i) putchar('\t'); - printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.getSize(), obj.getSize()); + printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.size(), obj.size()); if (obj.isForm()) { auto& form = dynamic_cast(obj); @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) try { MmapFile mmap{iffFile}; - IffFile iff{mmap.data(), mmap.size()}; + IffFile iff{mmap}; if (printStructure) { unsigned blobCount = 0, subdoc = 0; diff --git a/mvedecode.cc b/mvedecode.cc index 2db445e..1323f86 100644 --- a/mvedecode.cc +++ b/mvedecode.cc @@ -87,9 +87,9 @@ int main(int argc, char *argv[]) { if (!object) // Wasn't a CRC, try as name object = tre->openName(objectSpec); - mve = std::make_unique(object.data(), object.size()); + mve = std::make_unique(object); } else - mve = std::make_unique(mmap.data(), mmap.size()); + mve = std::make_unique(mmap); if (play) { Renderer renderer; diff --git a/objdecode.cc b/objdecode.cc index df8946d..61b3c01 100644 --- a/objdecode.cc +++ b/objdecode.cc @@ -17,21 +17,25 @@ #include "game/GSShowObject.hh" void usage(char *argv0) { - fprintf(stderr, "Usage: %s [-h] (tre-file name/crc)/iff-file\n", argv0); + fprintf(stderr, "Usage: %s [-h] [-ppalt] (tre-file name/crc)/iff-file\n", argv0); fprintf(stderr, "\tAttempt to decode the object stored in iff-file, or in the\n\tiff-object \"name\"/\"crc\" contained in tre-file\n"); + fprintf(stderr, "\t-p palt\tUse palette \"palt\""); fprintf(stderr, "\t-h\tPrint this help\n"); } int main(int argc, char *argv[]) { - std::string inFile, objectSpec; + std::string inFile, objectSpec, paltFile = "tmp/1DC61F50"; bool useTre = false; { int opt; - while ((opt = getopt(argc, argv, "h")) != -1) { + while ((opt = getopt(argc, argv, "hp:")) != -1) { switch (opt) { case 'h': usage(argv[0]); return 0; + case 'p': + paltFile = optarg; + break; default: usage(argv[0]); return 1; @@ -52,8 +56,8 @@ int main(int argc, char *argv[]) { } try { - MmapFile paltMmap{"tmp/1DC61F50"}; - PaletteDecoder palt{paltMmap.data(), paltMmap.size()}; + MmapFile paltMmap{paltFile}; + PaletteDecoder palt{paltMmap}; MmapFile mmap{inFile}; @@ -77,9 +81,9 @@ int main(int argc, char *argv[]) { if (!object) // Wasn't a CRC, try as name object = tre->openName(objectSpec); - obj = std::make_unique(object.data(), object.size()); + obj = std::make_unique(object); } else - obj = std::make_unique(mmap.data(), mmap.size()); + obj = std::make_unique(mmap); render::Renderer renderer; renderer.pushGS(std::make_unique(renderer, *obj, palt)); diff --git a/treexplore.cc b/treexplore.cc index feaa0ec..98eb399 100644 --- a/treexplore.cc +++ b/treexplore.cc @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) { continue; auto f = file.openName(name); try { - IffFile iff{f.data(), f.size()}; + IffFile iff{f}; printf("%s:\n", name.c_str()); iff.printStructure(1); } catch(FormatException &ex) { @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) { for(auto crc : file.getCRCs()) { auto f = file.openCRC(crc); try { - IffFile iff{f.data(), f.size()}; + IffFile iff{f}; printf("%.8x:\n", crc); iff.printStructure(1); } catch(FormatException &ex) { diff --git a/util.hh b/util.hh index 67d8232..d867b5a 100644 --- a/util.hh +++ b/util.hh @@ -5,23 +5,24 @@ #include #include "common.hh" +#include "Resource.hh" -class MmapFile { +class MmapFile : public Resource { public: MmapFile(std::string fileName); MmapFile(MmapFile const& copy) = delete; MmapFile(MmapFile && move); - ~MmapFile(); + ~MmapFile() override; MmapFile& operator=(MmapFile const& copy) = delete; MmapFile& operator=(MmapFile && move); std::string const& name() const; - size_t size() const; - uint8_t const* data() const; + size_t size() const override; + uint8_t const* data() const override; - operator bool() const; + operator bool() const override; private: std::string name_; FILEUPtr fd_;