Skip to content

Commit

Permalink
Refactor: Re-implemented FileDirectory as a specialization of de::Pat…
Browse files Browse the repository at this point in the history
…hDirectory
  • Loading branch information
danij-deng committed Aug 11, 2012
1 parent 066101a commit 2a3646c
Show file tree
Hide file tree
Showing 5 changed files with 476 additions and 402 deletions.
261 changes: 154 additions & 107 deletions doomsday/engine/portable/include/filedirectory.h
@@ -1,25 +1,32 @@
/**\file filedirectory.h
*\section License
* License: GPL
* Online License Link: http://www.gnu.org/licenses/gpl.html
/**
* @file filedirectory.h
*
* FileDirectory. Core system component representing a hierarchical file path
* structure.
*
*\author Copyright © 2003-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*\author Copyright © 2009-2012 Daniel Swanson <danij@dengine.net>
* A specialization of de::PathDirectory which implements automatic population
* of the directory itself from the virtual file system.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* @note Paths are resolved prior to pushing them into the directory.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* @ingroup fs
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
* @authors Copyright &copy; 2003-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright &copy; 2009-2012 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#ifndef LIBDENG_FILEDIRECTORY_H
Expand All @@ -29,127 +36,167 @@
#include "pathdirectory.h"

#ifdef __cplusplus
extern "C" {

namespace de {

class FileDirectory : private PathDirectory
{
public:
/**
* @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).
*/
explicit FileDirectory(const char* basePath=NULL);
~FileDirectory();

/**
* Clear this file directory's contents.
*/
void clear();

/**
* Find a path in this directory.
*
* @param type If a valid path type only consider nodes of this type.
* @param searchPath Relative or absolute path.
* @param searchDelimiter Fragments of @a searchPath are delimited by this character.
* @param foundPath If not @c NULL, the full path of the node is written back here if found.
* @param foundDelimiter Delimiter to be used when composing @a foundPath.
*
* @return @c true iff successful.
*/
bool find(pathdirectorynode_type_t nodeType, const char* searchPath,
char searchDelimiter, ddstring_t* foundPath, char foundDelimiter);

/**
* Add a new set of paths. Duplicates are automatically pruned.
*
* @param flags @ref searchPathFlags
* @param paths One or more paths.
* @param pathsCount Number of elements in @a paths.
* @param callback Callback function ptr.
* @param parameters Passed to the callback.
*/
void addPaths(int flags, const Uri* const* searchPaths, uint searchPathsCount,
int (*callback) (struct pathdirectorynode_s* node, void* parameters)=NULL,
void* parameters=NULL);

/**
* Add a new set of paths from a path list. Duplicates are automatically pruned.
*
* @param flags @ref searchPathFlags
* @param pathList One or more paths separated by semicolons.
* @param callback Callback function ptr.
* @param parameters Passed to the callback.
*/
void addPathList(int flags, const char* pathList,
int (*callback) (struct pathdirectorynode_s*, void*)=NULL, void* parameters=NULL);

/**
* Collate all paths in the directory into a list.
*
* @param flags @ref pathComparisonFlags
* @param delimiter Fragments of the path will be delimited by this character.
* @param count Number of visited paths is written back here.
*
* @return The allocated list; it is the responsibility of the caller to Str_Free()
* each string in the list and free() the list itself.
*/
ddstring_t* collectPaths(int flags, char delimiter, size_t* count);

#if _DEBUG
static void debugPrint(FileDirectory* inst);
static void debugPrintHashDistribution(FileDirectory* inst);
#endif

/**
* Callback function type for FileDirectory::Iterate
*
* @param node PathDirectoryNode being processed.
* @param parameters User data passed to this.
* @return Non-zero if iteration should stop.
*/
typedef pathdirectory_iteratecallback_t filedirectory_iteratecallback_t;
private:
void clearNodeInfo();

de::PathDirectoryNode* addPathNodes(const ddstring_t* rawPath);

int addChildNodes(de::PathDirectoryNode* node, int flags,
int (*callback) (struct pathdirectorynode_s* node, void* parameters),
void* parameters);

public: /// @todo Should be private.
/**
* @param filePath Possibly-relative path to an element in the virtual file system.
* @param flags @ref searchPathFlags
* @param callback If not @c NULL the callback's logic dictates whether iteration continues.
* @param parameters Passed to the callback.
* @param nodeType Type of element, either a branch (directory) or a leaf (file).
*
* @return Non-zero if the current iteration should stop else @c 0.
*/
int addPathNodesAndMaybeDescendBranch(bool descendBranches, const ddstring_t* filePath,
pathdirectorynode_type_t nodeType,
int flags,
int (*callback) (struct pathdirectorynode_s* node, void* parameters),
void* parameters);

private:
/// Used with relative path directories.
ddstring_t* basePath;

/// Used with relative path directories.
de::PathDirectoryNode* baseNode;
};

} // namespace de

/// Const variant.
typedef pathdirectory_iterateconstcallback_t filedirectory_iterateconstcallback_t;
extern "C" {
#endif

/**
* FileDirectory. Core system component representing a hierarchical
* file path structure.
*
* A specialization of de::PathDirectory which implements automatic
* population of the directory itself from the virtual file system.
* Also, paths are resolved prior to pushing them into the directory.
*
* @todo Perhaps this should be derived from PathDirectory instead of
* encapsulating an instance of it?
*
* @ingroup fs
* C wrapper API:
*/

struct filedirectory_s; // The filedirectory instance (opaque).
typedef struct filedirectory_s FileDirectory;

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 char* basePath, const ddstring_t* searchPathList, int flags);
FileDirectory* FileDirectory_NewWithPathList(const char* basePath, const char* searchPathList, int flags);

void FileDirectory_Delete(FileDirectory* fd);

/**
* Clear the directory contents.
*/
void FileDirectory_Clear(FileDirectory* fd);

/**
* Resolve and collate all paths in the directory into a list.
*
* @param fd FileDirectory instance.
* @param type If a valid type, only paths of this type will be visited.
* @param count Number of visited paths is written back here.
*
* @return Ptr to the allocated list; it is the responsibility of the caller to
* Str_Free each string in the list and Z_Free the list itself.
*/
ddstring_t* FileDirectory_AllPaths(FileDirectory* fd, pathdirectorynode_type_t type, size_t* count);

/**
* Add a new set of paths. Duplicates are automatically pruned.
*
* @param fd FileDirectory instance.
* @param flags @see searchPathFlags
* @param paths One or more paths.
* @param pathsCount Number of elements in @a paths.
* @param callback Callback function ptr.
* @param parameters Passed to the callback.
*/
void FileDirectory_AddPaths3(FileDirectory* fd, int flags, const Uri* const* paths, uint pathsCount,
int (*callback) (PathDirectoryNode* node, void* parameters), void* parameters);
void FileDirectory_AddPaths2(FileDirectory* fd, int flags, const Uri* const* paths, uint pathsCount,
int (*callback) (PathDirectoryNode* node, void* parameters)); /*parameters=NULL*/
void FileDirectory_AddPaths(FileDirectory* fd, int flags, const Uri* const* paths, uint pathsCount); /*callback=NULL*/

/**
* Add a new set of paths from a path list. Duplicates are automatically pruned.
*
* @param fd FileDirectory instance.
* @param flags @see searchPathFlags
* @param pathList One or more paths separated by semicolons.
* @param callback Callback function ptr.
* @param parameters Passed to the callback.
*/
void FileDirectory_AddPathList3(FileDirectory* fd, int flags, const char* pathList,
int (*callback) (PathDirectoryNode* node, void* parameters), void* parameters);
void FileDirectory_AddPathList2(FileDirectory* fd, int flags, const char* pathList,
int (*callback) (PathDirectoryNode* node, void* parameters)); /*parameters=NULL*/
void FileDirectory_AddPathList(FileDirectory* fd, int flags, const char* pathList); /*callback=NULL*/

boolean FileDirectory_Find(FileDirectory* fd, pathdirectorynode_type_t type,
const char* searchPath, char searchDelimiter, ddstring_t* foundPath, char foundDelimiter);

/**
* Find a path in the directory.
*
* @param fd FileDirectory instance.
* @param type If a valid path type only consider nodes of this type.
* @param searchPath Relative or absolute path.
* @param searchDelimiter Fragments of @a searchPath are delimited by this character.
* @param foundPath If not @c NULL, the full path of the node is written back here if found.
* @param foundDelimiter Delimiter to be used when composing @a foundPath.
* Callback function type for FileDirectory::Iterate
*
* @return @c true, iff successful.
* @param node PathDirectoryNode being processed.
* @param parameters User data passed to this.
* @return Non-zero if iteration should stop.
*/
boolean FileDirectory_Find(FileDirectory* fd, pathdirectorynode_type_t type,
const char* searchPath, char searchDelimiter, ddstring_t* foundPath, char foundDelimiter);
typedef pathdirectory_iteratecallback_t filedirectory_iteratecallback_t;

/// Const variant.
typedef pathdirectory_iterateconstcallback_t filedirectory_iterateconstcallback_t;

/**
* Iterate over nodes in the directory making a callback for each.
* Iteration ends when all nodes have been visited or a callback returns non-zero.
*
* @param fd FileDirectory instance.
* @param type If a valid path type only process nodes of this type.
* @param parent If not @c NULL, only process child nodes of this node.
* @param callback Callback function ptr.
* @param parameters Passed to the callback.
* @param fd FileDirectory instance.
* @param type If a valid path type only process nodes of this type.
* @param parent If not @c NULL, only process child nodes of this node.
* @param callback Callback function ptr.
* @param parameters Passed to the callback.
*
* @return @c 0 iff iteration completed wholly.
*/
Expand All @@ -164,8 +211,8 @@ int FileDirectory_Iterate_Const(const FileDirectory* fd, pathdirectorynode_type_
filedirectory_iterateconstcallback_t callback); /*parameters=NULL*/

#if _DEBUG
void FileDirectory_Print(FileDirectory* fd);
void FileDirectory_PrintHashDistribution(FileDirectory* fd);
void FileDirectory_DebugPrint(FileDirectory* fd);
void FileDirectory_DebugPrintHashDistribution(FileDirectory* fd);
#endif

#ifdef __cplusplus
Expand Down
42 changes: 19 additions & 23 deletions doomsday/engine/portable/include/pathdirectory.h
@@ -1,25 +1,23 @@
/**\file
*\section License
* License: GPL
* Online License Link: http://www.gnu.org/licenses/gpl.html
*
*\author Copyright © 2003-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*\author Copyright © 2009-2012 Daniel Swanson <danij@dengine.net>
/**
* @file pathdirectory.h
* @ingroup base
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* @authors Copyright &copy; 2003-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright &copy; 2009-2012 Daniel Swanson <danij@dengine.net>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#ifndef LIBDENG_PATHDIRECTORY_H
Expand Down Expand Up @@ -211,7 +209,7 @@ class PathDirectory

public:
explicit PathDirectory(int flags=0);
~PathDirectory();
virtual ~PathDirectory();

/// @return Number of unique paths in the directory.
uint size() const { return size_; }
Expand Down Expand Up @@ -271,8 +269,6 @@ class PathDirectory
/**
* Collate all paths in the directory into a list.
*
* @todo Does this really belong here (perhaps a class static non-member)?
*
* @param flags @ref pathComparisonFlags
* @param delimiter Fragments of the path will be delimited by this character.
* @param count Number of visited paths is written back here.
Expand All @@ -295,7 +291,7 @@ class PathDirectory
*/
static ushort hashPathFragment(const char* fragment, size_t len, char delimiter);

static void debugPrint(PathDirectory* pd, char delimiter);
static void debugPrint(PathDirectory* pd, char delimiter='/');
static void debugPrintHashDistribution(PathDirectory* pd);

private:
Expand Down

0 comments on commit 2a3646c

Please sign in to comment.