diff --git a/doomsday/engine/portable/include/abstractfile.h b/doomsday/engine/portable/include/abstractfile.h index 76e009bd50..932a8860ac 100644 --- a/doomsday/engine/portable/include/abstractfile.h +++ b/doomsday/engine/portable/include/abstractfile.h @@ -82,21 +82,17 @@ class AbstractFile uint _order; /** - * Initialize this resource. - * * @param type File type identifier. * @param path Path to this file in the virtual file system. - * @param file Handle to the file. AbstractFile takes ownership of the handle. + * @param file Handle to the file. Ownership of the handle is given to this instance. * @param info Lump info descriptor for the file. A copy is made. - * - * @return This instance. */ - AbstractFile& init(filetype_t type, char const* path, DFile* file, LumpInfo const* info); + AbstractFile(filetype_t type_, char const* path_, DFile* file, LumpInfo const* info_); /** * Release all memory acquired for objects linked with this resource. */ - void destroy(); + ~AbstractFile(); /** * @return Type of this resource @see filetype_t @@ -175,11 +171,6 @@ extern "C" { struct abstractfile_s; // The abstractfile instance (opaque) typedef struct abstractfile_s AbstractFile; -AbstractFile* AbstractFile_Init(AbstractFile* af, filetype_t type, - char const* path, DFile* file, LumpInfo const* info); - -void AbstractFile_Destroy(AbstractFile* af); - filetype_t AbstractFile_Type(AbstractFile const* af); LumpInfo const* AbstractFile_Info(AbstractFile const* af); @@ -211,6 +202,8 @@ int AbstractFile_LumpCount(AbstractFile* af); /// @todo Refactor away: AbstractFile* UnknownFile_New(DFile* file, char const* path, LumpInfo const* info); +void UnknownFile_Delete(AbstractFile* af); + #ifdef __cplusplus } // extern "C" #endif diff --git a/doomsday/engine/portable/include/lumpfile.h b/doomsday/engine/portable/include/lumpfile.h index 0f6d230f6d..a3c4125052 100644 --- a/doomsday/engine/portable/include/lumpfile.h +++ b/doomsday/engine/portable/include/lumpfile.h @@ -37,13 +37,8 @@ namespace de { /** * LumpFile. Runtime representation of a lump-file for use with LumpDirectory */ -class LumpFile +class LumpFile : public AbstractFile { -public: - /// Base file instance. - /// @todo Inherit from this instead. - AbstractFile base; - public: LumpFile(DFile& file, char const* path, LumpInfo const& info); ~LumpFile(); diff --git a/doomsday/engine/portable/include/wadfile.h b/doomsday/engine/portable/include/wadfile.h index fd66d54106..7ebdc0e8d2 100644 --- a/doomsday/engine/portable/include/wadfile.h +++ b/doomsday/engine/portable/include/wadfile.h @@ -50,13 +50,8 @@ class PathDirectoryNode; /** * WadFile. Runtime representation of an opened WAD file. */ -class WadFile +class WadFile : public AbstractFile { -public: - /// Base file instance. - /// @todo Inherit from this instead. - AbstractFile base; - public: WadFile(DFile& file, char const* path, LumpInfo const& info); ~WadFile(); diff --git a/doomsday/engine/portable/include/zipfile.h b/doomsday/engine/portable/include/zipfile.h index 06fdbdd2a9..dca5e899ad 100644 --- a/doomsday/engine/portable/include/zipfile.h +++ b/doomsday/engine/portable/include/zipfile.h @@ -52,13 +52,8 @@ class PathDirectoryNode; /** * ZipFile. Runtime representation of an opened ZIP file. */ -class ZipFile +class ZipFile : AbstractFile { -public: - /// Base file instance. - /// @todo Inherit from this instead. - AbstractFile base; - public: ZipFile(DFile& file, char const* path, LumpInfo const& info); ~ZipFile(); diff --git a/doomsday/engine/portable/src/abstractfile.cpp b/doomsday/engine/portable/src/abstractfile.cpp index 499aec59fd..88f0e83113 100644 --- a/doomsday/engine/portable/src/abstractfile.cpp +++ b/doomsday/engine/portable/src/abstractfile.cpp @@ -28,25 +28,21 @@ #include "abstractfile.h" -de::AbstractFile& de::AbstractFile::init(filetype_t type, char const* path, - DFile* file, const LumpInfo* info) +de::AbstractFile::AbstractFile(filetype_t type_, char const* path_, DFile* file, LumpInfo const* info_) + : _type(type_), _file(file) { // Used to favor newer files when duplicates are pruned. static uint fileCounter = 0; - DENG2_ASSERT(VALID_FILETYPE(type) && info); - + DENG2_ASSERT(VALID_FILETYPE(type_) && info_); _order = fileCounter++; - _type = type; - _file = file; + _flags.startup = false; _flags.custom = true; - Str_Init(&_path); Str_Set(&_path, path); - F_CopyLumpInfo(&_info, info); - - return *this; + Str_Init(&_path); Str_Set(&_path, path_); + F_CopyLumpInfo(&_info, info_); } -void de::AbstractFile::destroy() +de::AbstractFile::~AbstractFile() { Str_Free(&_path); F_DestroyLumpInfo(&_info); @@ -131,19 +127,6 @@ void de::AbstractFile::setCustom(bool yes) DENG2_ASSERT(inst); \ de::AbstractFile const* self = TOINTERNAL_CONST(inst) -AbstractFile* AbstractFile_Init(AbstractFile* af, filetype_t type, - char const* path, DFile* file, const LumpInfo* info) -{ - SELF(af); - return reinterpret_cast(&self->init(type, path, file, info)); -} - -void AbstractFile_Destroy(AbstractFile* af) -{ - SELF(af); - self->destroy(); -} - filetype_t AbstractFile_Type(AbstractFile const* af) { SELF_CONST(af); @@ -218,7 +201,17 @@ void AbstractFile_SetCustom(AbstractFile* af, boolean yes) AbstractFile* UnknownFile_New(DFile* file, char const* path, LumpInfo const* info) { - de::AbstractFile* af = new de::AbstractFile(); + de::AbstractFile* af = new de::AbstractFile(FT_UNKNOWNFILE, path, file, info); if(!af) LegacyCore_FatalError("UnknownFile_New: Failed to instantiate new AbstractFile."); - return reinterpret_cast(&af->init(FT_UNKNOWNFILE, path, file, info)); + return reinterpret_cast(af); +} + +void UnknownFile_Delete(AbstractFile* af) +{ + if(af) + { + SELF(af); + F_ReleaseFile(reinterpret_cast(self)); + delete self; + } } diff --git a/doomsday/engine/portable/src/fs_main.c b/doomsday/engine/portable/src/fs_main.c index ba835c225f..b010816d11 100644 --- a/doomsday/engine/portable/src/fs_main.c +++ b/doomsday/engine/portable/src/fs_main.c @@ -959,15 +959,10 @@ void F_Delete(DFile* file) DFile_Close(file); switch(AbstractFile_Type(af)) { - case FT_UNKNOWNFILE: - F_ReleaseFile(af); - AbstractFile_Destroy(af); - free(af); - break; - - case FT_ZIPFILE: ZipFile_Delete( ( ZipFile*)af); break; - case FT_WADFILE: WadFile_Delete( ( WadFile*)af); break; - case FT_LUMPFILE: LumpFile_Delete((LumpFile*)af); break; + case FT_UNKNOWNFILE: UnknownFile_Delete( af); break; + case FT_ZIPFILE: ZipFile_Delete( ( ZipFile*)af); break; + case FT_WADFILE: WadFile_Delete( ( WadFile*)af); break; + case FT_LUMPFILE: LumpFile_Delete((LumpFile*)af); break; default: Con_Error("F_Delete: Invalid file type %i.", AbstractFile_Type(af)); exit(1); // Unreachable. diff --git a/doomsday/engine/portable/src/lumpfile.cpp b/doomsday/engine/portable/src/lumpfile.cpp index e2442fecab..6d837e3b33 100644 --- a/doomsday/engine/portable/src/lumpfile.cpp +++ b/doomsday/engine/portable/src/lumpfile.cpp @@ -30,20 +30,18 @@ #include de::LumpFile::LumpFile(DFile& file, char const* path, LumpInfo const& info) -{ - reinterpret_cast(this)->init(FT_LUMPFILE, path, &file, &info); -} + : AbstractFile(FT_LUMPFILE, path, &file, &info) +{} de::LumpFile::~LumpFile() { F_ReleaseFile(reinterpret_cast(this)); - reinterpret_cast(this)->destroy(); } LumpInfo const* de::LumpFile::lumpInfo(int /*lumpIdx*/) { // Lump files are special cases for this *is* the lump. - return reinterpret_cast(this)->info(); + return this->info(); } int de::LumpFile::lumpCount() diff --git a/doomsday/engine/portable/src/wadfile.cpp b/doomsday/engine/portable/src/wadfile.cpp index 580b97aa6c..a872ecdbe5 100644 --- a/doomsday/engine/portable/src/wadfile.cpp +++ b/doomsday/engine/portable/src/wadfile.cpp @@ -209,8 +209,8 @@ struct de::WadFile::Instance // We'll load the lump directory using one continous read into a temporary // local buffer before we process it into our runtime representation. wadlumprecord_t* arcRecords = new wadlumprecord_t[arcRecordsCount]; - DFile_Seek(self->base._file, arcRecordsOffset, SEEK_SET); - DFile_Read(self->base._file, (uint8_t*)arcRecords, arcRecordsCount * sizeof(*arcRecords)); + DFile_Seek(self->_file, arcRecordsOffset, SEEK_SET); + DFile_Read(self->_file, (uint8_t*)arcRecords, arcRecordsCount * sizeof(*arcRecords)); // Reserve a small work buffer for processing archived lump names. ddstring_t absPath; @@ -228,9 +228,9 @@ struct de::WadFile::Instance record->baseOffset = de::littleEndianByteOrder.toNative(arcRecord->filePos); record->info.size = de::littleEndianByteOrder.toNative(arcRecord->size); record->info.compressedSize = record->info.size; - record->info.container = reinterpret_cast(&self->base); + record->info.container = reinterpret_cast(self); // The modification date is inherited from the file (note recursion). - record->info.lastModified = reinterpret_cast(&self->base)->lastModified(); + record->info.lastModified = self->lastModified(); record->info.lumpIdx = i; // Determine the name for this lump in the VFS. @@ -281,8 +281,8 @@ struct de::WadFile::Instance }; de::WadFile::WadFile(DFile& file, char const* path, LumpInfo const& info) + : AbstractFile(FT_WADFILE, path, &file, &info) { - reinterpret_cast(this)->init(FT_WADFILE, path, &file, &info); d = new Instance(this, file, path); } @@ -291,7 +291,6 @@ de::WadFile::~WadFile() F_ReleaseFile(reinterpret_cast(this)); clearLumpCache(); delete d; - reinterpret_cast(this)->destroy(); } bool de::WadFile::isValidIndex(int lumpIdx) @@ -414,7 +413,7 @@ uint8_t const* de::WadFile::cacheLump(int lumpIdx) const LumpInfo* info = lumpInfo(lumpIdx); LOG_TRACE("\"%s:%s\" (%lu bytes%s)") - << F_PrettyPath(Str_Text(reinterpret_cast(this)->path())) + << F_PrettyPath(Str_Text(path())) << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))) << (unsigned long) info->size << (info->compressedSize != info->size? ", compressed" : ""); @@ -441,8 +440,7 @@ de::WadFile& de::WadFile::unlockLump(int lumpIdx) { LOG_AS("WadFile::unlockLump"); LOG_TRACE("\"%s:%s\"") - << F_PrettyPath(Str_Text(reinterpret_cast(this)->path())) - << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))); + << F_PrettyPath(Str_Text(path())) << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))); if(isValidIndex(lumpIdx)) { @@ -471,7 +469,7 @@ size_t de::WadFile::readLumpSection(int lumpIdx, uint8_t* buffer, size_t startOf if(!lrec) return 0; LOG_TRACE("\"%s:%s\" (%lu bytes%s) [%lu +%lu]") - << F_PrettyPath(Str_Text(reinterpret_cast(this)->path())) + << F_PrettyPath(Str_Text(path())) << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))) << (unsigned long) lrec->info.size << (lrec->info.compressedSize != lrec->info.size? ", compressed" : "") @@ -491,8 +489,8 @@ size_t de::WadFile::readLumpSection(int lumpIdx, uint8_t* buffer, size_t startOf } } - DFile_Seek(base._file, lrec->baseOffset + startOffset, SEEK_SET); - size_t readBytes = DFile_Read(base._file, buffer, length); + DFile_Seek(_file, lrec->baseOffset + startOffset, SEEK_SET); + size_t readBytes = DFile_Read(_file, buffer, length); /// @todo Do not check the read length here. if(readBytes < length) diff --git a/doomsday/engine/portable/src/zipfile.cpp b/doomsday/engine/portable/src/zipfile.cpp index a00d938a3d..0d9af17ffa 100644 --- a/doomsday/engine/portable/src/zipfile.cpp +++ b/doomsday/engine/portable/src/zipfile.cpp @@ -259,10 +259,10 @@ struct de::ZipFile::Instance int pos = CENTRAL_END_SIZE; // Offset from the end. while(pos < MAXIMUM_COMMENT_SIZE) { - DFile_Seek(self->base._file, -pos, SEEK_END); + DFile_Seek(self->_file, -pos, SEEK_END); // Is this the signature? - DFile_Read(self->base._file, (uint8_t*)&signature, sizeof(signature)); + DFile_Read(self->_file, (uint8_t*)&signature, sizeof(signature)); if(de::littleEndianByteOrder.toNative(signature) == SIG_END_OF_CENTRAL_DIR) return true; // Yes, this is it. @@ -280,15 +280,15 @@ struct de::ZipFile::Instance // Scan the end of the file for the central directory end record. if(!locateCentralDirectory()) - throw de::Error("ZipFile::readLumpDirectory", QString("Central directory in %1 not found").arg(Str_Text(reinterpret_cast(&self->base)->path()))); + throw de::Error("ZipFile::readLumpDirectory", QString("Central directory in %1 not found").arg(Str_Text(self->path()))); // Read the central directory end record. centralend_t summary; - readCentralEnd(*self->base._file, summary); + readCentralEnd(*self->_file, summary); // Does the summary say something we don't like? if(summary.diskEntryCount != summary.totalEntryCount) - throw de::Error("ZipFile::readLumpDirectory", QString("Multipart zip file \"%1\" not supported").arg(Str_Text(reinterpret_cast(&self->base)->path()))); + throw de::Error("ZipFile::readLumpDirectory", QString("Multipart zip file \"%1\" not supported").arg(Str_Text(self->path()))); // We'll load the file directory using one continous read into a temporary // local buffer before we process it into our runtime representation. @@ -296,8 +296,8 @@ struct de::ZipFile::Instance void* centralDirectory = M_Malloc(summary.size); if(!centralDirectory) throw de::Error("ZipFile::readLumpDirectory", QString("Failed on allocation of %1 bytes for temporary copy of the central centralDirectory").arg(summary.size)); - DFile_Seek(self->base._file, summary.offset, SEEK_SET); - DFile_Read(self->base._file, (uint8_t*)centralDirectory, summary.size); + DFile_Seek(self->_file, summary.offset, SEEK_SET); + DFile_Read(self->_file, (uint8_t*)centralDirectory, summary.size); /** * Pass 1: Validate support and count the number of lump records we need. @@ -347,16 +347,14 @@ struct de::ZipFile::Instance { if(pass != 0) continue; LOG_WARNING("Zip %s:'%s' uses an unsupported compression algorithm, ignoring.") - << Str_Text(reinterpret_cast(&self->base)->path()) - << Str_Text(&entryPath); + << Str_Text(self->path()) << Str_Text(&entryPath); } if(USHORT(header->flags) & ZFH_ENCRYPTED) { if(pass != 0) continue; LOG_WARNING("Zip %s:'%s' is encrypted.\n Encryption is not supported, ignoring.") - << Str_Text(reinterpret_cast(&self->base)->path()) - << Str_Text(&entryPath); + << Str_Text(self->path()) << Str_Text(&entryPath); } if(pass == 0) @@ -393,12 +391,12 @@ struct de::ZipFile::Instance } // The modification date is inherited from the real file (note recursion). - record->info.lastModified = reinterpret_cast(&self->base)->lastModified(); - record->info.container = reinterpret_cast(&self->base); + record->info.lastModified = self->lastModified(); + record->info.container = reinterpret_cast(self); // Read the local file header, which contains the extra field size (Info-ZIP!). - DFile_Seek(self->base._file, ULONG(header->relOffset), SEEK_SET); - DFile_Read(self->base._file, (uint8_t*)&localHeader, sizeof(localHeader)); + DFile_Seek(self->_file, ULONG(header->relOffset), SEEK_SET); + DFile_Read(self->_file, (uint8_t*)&localHeader, sizeof(localHeader)); record->baseOffset = ULONG(header->relOffset) + sizeof(localfileheader_t) + USHORT(header->fileNameSize) + USHORT(localHeader.extraFieldSize); @@ -439,7 +437,7 @@ struct de::ZipFile::Instance DENG2_ASSERT(lumpRecord && buffer); LOG_AS("ZipFile"); - DFile_Seek(self->base._file, lumpRecord->baseOffset, SEEK_SET); + DFile_Seek(self->_file, lumpRecord->baseOffset, SEEK_SET); if(lumpRecord->info.compressedSize != lumpRecord->info.size) { @@ -448,7 +446,7 @@ struct de::ZipFile::Instance if(!compressedData) throw de::Error("ZipFile::bufferLump", QString("Failed on allocation of %1 bytes for decompression buffer").arg(lumpRecord->info.compressedSize)); // Read the compressed data into a temporary buffer for decompression. - DFile_Read(self->base._file, compressedData, lumpRecord->info.compressedSize); + DFile_Read(self->_file, compressedData, lumpRecord->info.compressedSize); // Uncompress into the buffer provided by the caller. result = uncompressRaw(compressedData, lumpRecord->info.compressedSize, @@ -460,15 +458,15 @@ struct de::ZipFile::Instance else { // Read the uncompressed data directly to the buffer provided by the caller. - DFile_Read(self->base._file, buffer, lumpRecord->info.size); + DFile_Read(self->_file, buffer, lumpRecord->info.size); } return lumpRecord->info.size; } }; de::ZipFile::ZipFile(DFile& file, char const* path, LumpInfo const& info) + : AbstractFile(FT_ZIPFILE, path, &file, &info) { - reinterpret_cast(this)->init(FT_ZIPFILE, path, &file, &info); d = new Instance(this); } @@ -477,7 +475,6 @@ de::ZipFile::~ZipFile() F_ReleaseFile(reinterpret_cast(this)); clearLumpCache(); delete d; - reinterpret_cast(this)->destroy(); } bool de::ZipFile::isValidIndex(int lumpIdx) @@ -600,7 +597,7 @@ uint8_t const* de::ZipFile::cacheLump(int lumpIdx) const LumpInfo* info = lumpInfo(lumpIdx); LOG_TRACE("\"%s:%s\" (%lu bytes%s)") - << F_PrettyPath(Str_Text(reinterpret_cast(this)->path())) + << F_PrettyPath(Str_Text(path())) << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))) << (unsigned long) info->size << (info->compressedSize != info->size? ", compressed" : ""); @@ -627,8 +624,7 @@ de::ZipFile& de::ZipFile::unlockLump(int lumpIdx) { LOG_AS("ZipFile::unlockLump"); LOG_TRACE("\"%s:%s\"") - << F_PrettyPath(Str_Text(reinterpret_cast(this)->path())) - << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))); + << F_PrettyPath(Str_Text(path())) << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))); if(isValidIndex(lumpIdx)) { @@ -657,7 +653,7 @@ size_t de::ZipFile::readLumpSection(int lumpIdx, uint8_t* buffer, size_t startOf if(!lrec) return 0; LOG_TRACE("\"%s:%s\" (%lu bytes%s) [%lu +%lu]") - << F_PrettyPath(Str_Text(reinterpret_cast(this)->path())) + << F_PrettyPath(Str_Text(path())) << F_PrettyPath(Str_Text(composeLumpPath(lumpIdx, '/'))) << (unsigned long) lrec->info.size << (lrec->info.compressedSize != lrec->info.size? ", compressed" : "")