Skip to content

Commit

Permalink
File Sys|Fixed: -iwad failed locating iwads in root of Doomsday insta…
Browse files Browse the repository at this point in the history
…ll dir

FileDirectory by default will attempt to remove the engine's install
dir when inserting paths, i.e., it tries to make all paths relative
when it can so as to compress the data (there is no need to represent
the base multiple times). Consequently when presented with a path
exactly equal to the install dir; the resultant relative path became
a zero-length string, which was then not added to the directory.

FileDirectory can now be initialized in one of two distinct modes:

A) Relative mode
Both relative and absolute paths may be inserted into the directory.
The base path is defined during instantiation. An attempt is made to
transform all paths into relative ones upon being added into the
directory.

B) Absolute mode
Only absolute paths may be inserted into the directory. All paths are
represented using their fully qualified paths (i.e., the base is not
removed from paths).

In relative mode, FileDirectory will now insert a new node into it's
internal PathDirectory to represent the symbolic "./" directory when
it is first added. This symbolic node is used to represent the base
directory which it will by default remove in the process of making
paths relative.
  • Loading branch information
danij-deng committed Feb 22, 2012
1 parent 71ea346 commit e1862e7
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 26 deletions.
10 changes: 7 additions & 3 deletions doomsday/engine/portable/include/filedirectory.h
Expand Up @@ -58,17 +58,21 @@ typedef pathdirectory_iterateconstcallback_t filedirectory_iterateconstcallback_
struct filedirectory_s; // The filedirectory instance (opaque).
typedef struct filedirectory_s FileDirectory;

FileDirectory* FileDirectory_New(void);
FileDirectory* FileDirectory_New(const char* basePath);

/**
* Construct a new FileDirectory instance, populating it with nodes
* for the given search paths.
*
* @param basePath Used with directories which represent the internal paths
* natively as relative paths. @c NULL means only absolute
* paths will be added to the directory (attempts to add
* relative paths will fail silently).
* @param searchPathList List of search paths. @c NULL terminated.
* @param flags @see searchPathFlags
*/
FileDirectory* FileDirectory_NewWithPathListStr(const ddstring_t* searchPathList, int flags);
FileDirectory* FileDirectory_NewWithPathList(const char* searchPathList, int flags);
FileDirectory* FileDirectory_NewWithPathListStr(const char* basePath, const ddstring_t* searchPathList, int flags);
FileDirectory* FileDirectory_NewWithPathList(const char* basePath, const char* searchPathList, int flags);

void FileDirectory_Delete(FileDirectory* fd);

Expand Down
92 changes: 73 additions & 19 deletions doomsday/engine/portable/src/filedirectory.c
Expand Up @@ -35,6 +35,12 @@ typedef struct filedirectory_nodeinfo_s {
struct filedirectory_s {
/// Path hash table.
PathDirectory* _pathDirectory;

/// Used with relative path directories.
ddstring_t* _basePath;

/// Used with relative path directories.
PathDirectoryNode* _baseNode;
};

typedef struct {
Expand Down Expand Up @@ -73,32 +79,57 @@ static PathDirectoryNode* attachMissingNodeInfo(PathDirectoryNode* node)
return node;
}

static PathDirectoryNode* addPathNodes(FileDirectory* fd, const ddstring_t* _path)
static PathDirectoryNode* addPathNodes(FileDirectory* fd, const ddstring_t* rawPath)
{
const ddstring_t* relPath;
const ddstring_t* path;
PathDirectoryNode* node;
ddstring_t path;
ddstring_t buf;

assert(fd);

if(!_path || Str_IsEmpty(_path)) return NULL;
if(!rawPath || Str_IsEmpty(rawPath)) return NULL;

// Let's try to make it a relative path.
if(F_IsAbsolute(_path))
if(fd->_basePath)
{
Str_Init(&path);
F_RemoveBasePath(&path, _path);
relPath = &path;
// Try to make it a relative path?
if(F_IsAbsolute(rawPath))
{
F_RemoveBasePath2(Str_InitStd(&buf), rawPath, fd->_basePath);
path = &buf;
}
else
{
path = rawPath;
}

// If this is equal to the base path, return that node.
if(Str_IsEmpty(path))
{
// Time to construct the relative base node?
// This node is purely symbolic, its only necessary for our internal use.
if(!fd->_baseNode)
{
fd->_baseNode = PathDirectory_Insert(fd->_pathDirectory, "./", '/');
attachMissingNodeInfo(fd->_baseNode);
}

if(path == &buf) Str_Free(&buf);
return fd->_baseNode;
}
}
else
{
relPath = _path;
// Do not add relative paths.
if(!F_IsAbsolute(rawPath))
{
return NULL;
}
}

node = PathDirectory_Insert(fd->_pathDirectory, Str_Text(relPath), '/');
node = PathDirectory_Insert(fd->_pathDirectory, Str_Text(path), '/');
attachMissingNodeInfo(node);

if(relPath == &path) Str_Free(&path);
if(path == &buf) Str_Free(&buf);

return node;
}
Expand Down Expand Up @@ -243,13 +274,27 @@ static void printUriList(const Uri* const* pathList, size_t pathCount, int inden
}
}

FileDirectory* FileDirectory_NewWithPathListStr(const ddstring_t* pathList, int flags)
FileDirectory* FileDirectory_NewWithPathListStr(const char* basePath,
const ddstring_t* pathList, int flags)
{
FileDirectory* fd = (FileDirectory*) malloc(sizeof *fd);
if(!fd)
Con_Error("FileDirectory::Construct: Failed on allocation of %lu bytes for new FileDirectory.", (unsigned long) sizeof *fd);

fd->_pathDirectory = PathDirectory_New();
fd->_baseNode = NULL;

if(basePath && basePath[0])
{
fd->_basePath = Str_Set(Str_NewStd(), basePath);
// Ensure path is correctly formed.
F_AppendMissingSlash(fd->_basePath);
}
else
{
fd->_basePath = NULL;
}

if(pathList)
{
size_t count;
Expand All @@ -260,7 +305,8 @@ FileDirectory* FileDirectory_NewWithPathListStr(const ddstring_t* pathList, int
return fd;
}

FileDirectory* FileDirectory_NewWithPathList(const char* pathList, int flags)
FileDirectory* FileDirectory_NewWithPathList(const char* basePath,
const char* pathList, int flags)
{
FileDirectory* fd;
ddstring_t _pathList, *paths = NULL;
Expand All @@ -271,14 +317,14 @@ FileDirectory* FileDirectory_NewWithPathList(const char* pathList, int flags)
Str_Set(&_pathList, pathList);
paths = &_pathList;
}
fd = FileDirectory_NewWithPathListStr(paths, flags);
fd = FileDirectory_NewWithPathListStr(basePath, paths, flags);
if(len != 0) Str_Free(paths);
return fd;
}

FileDirectory* FileDirectory_New(void)
FileDirectory* FileDirectory_New(const char* basePath)
{
return FileDirectory_NewWithPathListStr(NULL, 0);
return FileDirectory_NewWithPathListStr(basePath, NULL, 0);
}

static int deleteNodeInfo(PathDirectoryNode* node, void* paramaters)
Expand All @@ -300,6 +346,7 @@ void FileDirectory_Delete(FileDirectory* fd)
assert(fd);
clearNodeInfo(fd);
if(fd->_pathDirectory) PathDirectory_Delete(fd->_pathDirectory);
if(fd->_basePath) Str_Delete(fd->_basePath);
free(fd);
}

Expand All @@ -308,6 +355,7 @@ void FileDirectory_Clear(FileDirectory* fd)
assert(fd);
clearNodeInfo(fd);
PathDirectory_Clear(fd->_pathDirectory);
fd->_baseNode = NULL;
}

void FileDirectory_AddPaths3(FileDirectory* fd, int flags, const Uri* const* paths,
Expand Down Expand Up @@ -416,6 +464,12 @@ boolean FileDirectory_Find(FileDirectory* fd, pathdirectorynode_type_t nodeType,
Str_Init(&searchPath); Str_Set(&searchPath, _searchPath);
F_FixSlashes(&searchPath, &searchPath);

// Try to make it a relative path?
if(fd->_basePath && !F_IsAbsolute(&searchPath))
{
F_RemoveBasePath2(&searchPath, &searchPath, fd->_basePath);
}

// Perform the search.
flags = (nodeType == PT_LEAF? PCF_NO_BRANCH : PCF_NO_LEAF) | PCF_MATCH_FULL;
foundNode = PathDirectory_Find(fd->_pathDirectory, flags, Str_Text(&searchPath), searchDelimiter);
Expand Down Expand Up @@ -468,7 +522,7 @@ void FileDirectory_Print(FileDirectory* fd)
assert(fd);

Con_Printf("FileDirectory [%p]:\n", (void*)fd);
pathList = PathDirectory_CollectPaths(fd->_pathDirectory, PCF_NO_BRANCH, DIR_SEP_CHAR, &numFiles);
pathList = PathDirectory_CollectPaths(fd->_pathDirectory, 0, DIR_SEP_CHAR, &numFiles);
if(pathList)
{
qsort(pathList, numFiles, sizeof *pathList, comparePaths);
Expand All @@ -477,7 +531,7 @@ void FileDirectory_Print(FileDirectory* fd)

deletePathList(pathList, numFiles);
}
Con_Printf(" %lu %s in directory.\n", (unsigned long)numFiles, (numFiles==1? "file":"files"));
Con_Printf(" %lu %s in directory.\n", (unsigned long)numFiles, (numFiles==1? "path":"paths"));
}

void FileDirectory_PrintHashDistribution(FileDirectory* fd)
Expand Down
6 changes: 4 additions & 2 deletions doomsday/engine/portable/src/pathdirectory.c
Expand Up @@ -682,7 +682,7 @@ const ddstring_t* PathDirectory_GetFragment(PathDirectory* pd, const PathDirecto
return StringPool_String(pd->internPool.strings, PathDirectoryNode_InternId(node));
}

/// Calculate the total length of the final composed path.
// Calculate the total length of the final composed path.
static int PathDirectory_CalcPathLength(PathDirectory* pd, const PathDirectoryNode* node, char delimiter)
{
const int delimiterLen = delimiter? 1 : 0;
Expand All @@ -708,7 +708,9 @@ static int PathDirectory_CalcPathLength(PathDirectory* pd, const PathDirectoryNo
return requiredLen;
}

/// \assume @a foundPath already has sufficent characters reserved to hold the fully composed path.
/**
* @assume @a foundPath already has sufficent characters reserved to hold the fully composed path.
*/
static ddstring_t* PathDirectory_ConstructPath(PathDirectory* pd, const PathDirectoryNode* node,
ddstring_t* foundPath, char delimiter)
{
Expand Down
4 changes: 2 additions & 2 deletions doomsday/engine/portable/src/sys_reslocator.c
Expand Up @@ -691,7 +691,7 @@ static void createPackagesResourceNamespace(void)
Str_Delete(doomWadDir);
}

directory = FileDirectory_New();
directory = FileDirectory_New(ddBasePath);
rnamespace = F_CreateResourceNamespace(PACKAGES_RESOURCE_NAMESPACE_NAME, directory,
F_ComposeHashNameForFilePath, F_HashKeyForFilePathHashName, 0);

Expand Down Expand Up @@ -765,7 +765,7 @@ void F_CreateNamespacesForFileResourcePaths(void)
{
uint j, searchPathCount;
struct namespacedef_s* def = &defs[i];
FileDirectory* directory = FileDirectory_New();
FileDirectory* directory = FileDirectory_New(ddBasePath);
resourcenamespace_t* rnamespace = F_CreateResourceNamespace(def->name, directory,
F_ComposeHashNameForFilePath, F_HashKeyForFilePathHashName, def->flags);

Expand Down

0 comments on commit e1862e7

Please sign in to comment.