Skip to content

Commit

Permalink
Refactor|FS1: Restructured various file system logics
Browse files Browse the repository at this point in the history
Moved the logic of Game::isRequiredResource() into FS1::unloadFile()
and extracted the logic from FS1::zipLumpIndex() moving it into the
tryOpenLump() method.

The subsequently redundant FS1::zipLumpIndex() was removed.
  • Loading branch information
danij-deng committed Oct 20, 2012
1 parent a417cff commit 51da254
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 124 deletions.
11 changes: 0 additions & 11 deletions doomsday/engine/portable/include/fs_main.h
Expand Up @@ -192,17 +192,6 @@ namespace de
*/
LumpIndex const& nameIndexForLump(lumpnum_t& absoluteLumpNum) const;

/**
* Retrieve the FileInfo metadata record for a lump in the Zip lump index.
*
* @param path Path to search for (made absolute if necessary).
*
* @return Metadata record for the lump.
*
* @throws NotFoundError If the requested file could not be found.
*/
FileInfo const& zipFileInfo(char const* path);

/**
* Opens the given file (will be translated) for reading.
*
Expand Down
7 changes: 0 additions & 7 deletions doomsday/engine/portable/include/game.h
Expand Up @@ -130,11 +130,6 @@ class Game
*/
Game& addResource(resourceclass_t rclass, struct AbstractResource_s& record);

/**
* @return @c true iff @a absolutePath points to a required resource.
*/
bool isRequiredResource(char const* absolutePath);

bool allStartupResourcesFound() const;

/**
Expand Down Expand Up @@ -244,8 +239,6 @@ boolean Game_IsNullObject(Game const* game);

struct game_s* Game_AddResource(Game* game, resourceclass_t rclass, struct AbstractResource_s* record);

boolean Game_IsRequiredResource(Game* game, char const* absolutePath);

boolean Game_AllStartupResourcesFound(Game const* game);

Game* Game_SetPluginId(Game* game, pluginid_t pluginId);
Expand Down
158 changes: 90 additions & 68 deletions doomsday/engine/portable/src/fs_main.cpp
Expand Up @@ -255,29 +255,59 @@ struct FS1::Instance
bool allowDuplicate, FileInfo& retInfo)
{
DENG_ASSERT(path && path[0]);
try

// Convert to an absolute path.
AutoStr* absSearchPath = AutoStr_FromTextStd(path);
F_PrependBasePath(absSearchPath, absSearchPath);

FileInfo const* found = 0;

// First check the Zip lump index.
lumpnum_t lumpNum = zipLumpIndex.indexForPath(Str_Text(absSearchPath));
if(lumpNum >= 0)
{
found = &zipLumpIndex.lumpInfo(lumpNum);
}
// Nope. Any applicable dir/WAD redirects?
else if(!lumpMappings.empty())
{
FileInfo const& info = self->zipFileInfo(path);
// Do not read files twice.
if(!allowDuplicate && !self->checkFileId(path)) return 0;
// We must have an absolute path - prepend the CWD if necessary.
Str_Set(absSearchPath, path);
F_PrependWorkPath(absSearchPath, absSearchPath);

// Get a handle to the lump we intend to open.
/// @todo The way this buffering works is nonsensical it should not be done here
/// but should instead be deferred until the content of the lump is read.
FileHandle* hndl = FileHandleBuilder::fromFileLump(*info.container, info.lumpIdx, false/*dontBuffer*/);
DENG2_FOR_EACH(i, lumpMappings, LumpMappings::const_iterator)
{
LumpMapping const& mapping = *i;
QByteArray foundPathUtf8 = mapping.first.toUtf8();
if(qstricmp(foundPathUtf8.constData(), Str_Text(absSearchPath))) continue;

// Prepare a temporary info descriptor.
retInfo = info;
QByteArray foundLumpNameUtf8 = mapping.second.toUtf8();
lumpnum_t absoluteLumpNum = self->lumpNumForName(foundLumpNameUtf8.constData());
if(absoluteLumpNum < 0) continue;

return hndl;
found = &self->nameIndexForLump(absoluteLumpNum).lumpInfo(absoluteLumpNum);
}
}
catch(NotFoundError)
{} // Ignore this error.
return 0;

// Nothing?
if(!found) return 0;

// Do not read files twice.
if(!allowDuplicate && !self->checkFileId(path)) return 0;

// Get a handle to the lump we intend to open.
/// @todo The way this buffering works is nonsensical it should not be done here
/// but should instead be deferred until the content of the lump is read.
FileHandle* hndl = FileHandleBuilder::fromFileLump(*found->container, found->lumpIdx, false/*dontBuffer*/);

// Prepare a temporary info descriptor.
retInfo = *found;

return hndl;
}

de::FileHandle* tryOpenNativeFile(char const* path, char const* mymode, size_t baseOffset,
bool allowDuplicate, FileInfo& info)
bool allowDuplicate, FileInfo& info)
{
DENG_ASSERT(path && path[0]);

Expand All @@ -294,8 +324,9 @@ struct FS1::Instance
F_PrependWorkPath(nativePath, nativePath);
F_ToNativeSlashes(nativePath, nativePath);

// First try a real native file at this absolute path.
AutoStr* foundPath = 0;

// First try a real native file at this absolute path.
FILE* nativeFile = fopen(Str_Text(nativePath), mode);
if(nativeFile)
{
Expand Down Expand Up @@ -482,23 +513,59 @@ void FS1::deindex(de::File1& file)

bool FS1::unloadFile(char const* path, bool permitRequired, bool quiet)
{
FileList::iterator found = findListFileByPath(d->loadedFiles, path);
// Convert to an absolute path.
AutoStr* absolutePath = AutoStr_FromTextStd(path);
F_PrependBasePath(absolutePath, absolutePath);

FileList::iterator found = findListFileByPath(d->loadedFiles, Str_Text(absolutePath));
if(found == d->loadedFiles.end()) return false;

// Do not attempt to unload a resource required by the current game.
if(!permitRequired && reinterpret_cast<de::Game*>(App_CurrentGame())->isRequiredResource(path))
if(!permitRequired)
{
if(!quiet)
bool isRequired = false;

if(AbstractResource* const* records = reinterpret_cast<de::Game*>(App_CurrentGame())->resources(RC_PACKAGE, 0))
{
Con_Message("\"%s\" is required by the current game.\n"
"Required game files cannot be unloaded in isolation.\n", F_PrettyPath(path));
// Is this resource from a container?
lumpnum_t lumpNum = d->zipLumpIndex.indexForPath(Str_Text(absolutePath));
if(lumpNum >= 0)
{
// Yes; use the container's path instead.
FileInfo const& info = d->zipLumpIndex.lumpInfo(lumpNum);
Str_Copy(absolutePath, info.container->path());
}

for(AbstractResource* const* i = records; *i; i++)
{
AbstractResource* record = *i;
if(AbstractResource_ResourceFlags(record) & RF_STARTUP)
{
ddstring_t const* resolvedPath = AbstractResource_ResolvedPath(record, true);
if(resolvedPath && !Str_CompareIgnoreCase(resolvedPath, Str_Text(absolutePath)))
{
isRequired = true;
break;
}
}
}
}

if(isRequired)
{
if(!quiet)
{
Con_Message("\"%s\" is required by the current game.\n"
"Required game files cannot be unloaded in isolation.\n",
F_PrettyPath(Str_Text(absolutePath)));
}
return false;
}
return false;
}

if(!quiet && verbose >= 1)
{
Con_Message("Unloading \"%s\"...\n", F_PrettyPath(path));
Con_Message("Unloading \"%s\"...\n", F_PrettyPath(Str_Text(absolutePath)));
}

FileHandle& hndl = *(*found);
Expand Down Expand Up @@ -771,51 +838,6 @@ lumpnum_t FS1::lumpNumForName(char const* name, bool silent)
return d->logicalLumpNum(lumpNum);
}

FileInfo const& FS1::zipFileInfo(char const* path)
{
if(!path || !path[0]) throw NotFoundError("FS1::zipFileInfo", "No files found matching '" + QString(path) + "'");

/*
* First check the Zip directory.
*/

// Convert to an absolute path.
AutoStr* absSearchPath = AutoStr_FromTextStd(path);
F_PrependBasePath(absSearchPath, absSearchPath);

// Perform the search.
lumpnum_t lumpNum = d->zipLumpIndex.indexForPath(Str_Text(absSearchPath));
if(lumpNum >= 0)
{
return d->zipLumpIndex.lumpInfo(lumpNum);
}

/*
* Next try the dir/WAD redirects.
*/
if(!d->lumpMappings.empty())
{
// We must have an absolute path - prepend the CWD if necessary.
Str_Set(absSearchPath, path);
F_PrependWorkPath(absSearchPath, absSearchPath);

DENG2_FOR_EACH(i, d->lumpMappings, LumpMappings::const_iterator)
{
LumpMapping const& found = *i;
QByteArray foundPathUtf8 = found.first.toUtf8();
if(qstricmp(foundPathUtf8.constData(), Str_Text(absSearchPath))) continue;

QByteArray foundLumpNameUtf8 = found.second.toUtf8();
lumpnum_t absoluteLumpNum = lumpNumForName(foundLumpNameUtf8.constData());
if(absoluteLumpNum < 0) continue;

return nameIndexForLump(absoluteLumpNum).lumpInfo(absoluteLumpNum);
}
}

throw NotFoundError("FS1::zipFileInfo", "No files found matching '" + QString(path) + "'");
}

lumpnum_t FS1::openAuxiliary(char const* filePath, size_t baseOffset)
{
/// @todo Allow opening Zip files too.
Expand Down
38 changes: 0 additions & 38 deletions doomsday/engine/portable/src/game.cpp
Expand Up @@ -156,38 +156,6 @@ Game& Game::addResource(resourceclass_t rclass, AbstractResource& record)
return *this;
}

bool Game::isRequiredResource(char const* absolutePath)
{
AbstractResource* const* records = resources(RC_PACKAGE, 0);
if(records)
{
// Is this resource from a container?
try
{
FileInfo const& info = App_FileSystem()->zipFileInfo(absolutePath);
// Yes; use the container's path instead.
absolutePath = Str_Text(info.container->path());
}
catch(FS1::NotFoundError const&)
{} // Ignore this error.

for(AbstractResource* const* i = records; *i; i++)
{
AbstractResource* record = *i;
if(AbstractResource_ResourceFlags(record) & RF_STARTUP)
{
ddstring_t const* resolvedPath = AbstractResource_ResolvedPath(record, true);
if(resolvedPath && !Str_CompareIgnoreCase(resolvedPath, absolutePath))
{
return true;
}
}
}
}
// Not found, so no.
return false;
}

bool Game::allStartupResourcesFound() const
{
for(uint i = 0; i < RESOURCECLASS_COUNT; ++i)
Expand Down Expand Up @@ -410,12 +378,6 @@ struct game_s* Game_AddResource(struct game_s* game, resourceclass_t rclass, str
return game;
}

boolean Game_IsRequiredResource(struct game_s* game, char const* absolutePath)
{
SELF(game);
return self->isRequiredResource(absolutePath);
}

boolean Game_AllStartupResourcesFound(struct game_s const* game)
{
SELF_CONST(game);
Expand Down

0 comments on commit 51da254

Please sign in to comment.