diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/archive.cpp | 30 | ||||
| -rw-r--r-- | common/archive.h | 82 | 
2 files changed, 91 insertions, 21 deletions
diff --git a/common/archive.cpp b/common/archive.cpp index 96ead55abd..c39912bfe4 100644 --- a/common/archive.cpp +++ b/common/archive.cpp @@ -71,7 +71,7 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern)   */  class FSDirectoryMember : public ArchiveMember {  	FSNode 	_node; -   +  public:  	FSDirectoryMember(FSNode &node) : _node(node) {  	} @@ -98,13 +98,33 @@ FSDirectory::FSDirectory(const FSNode &node, int depth)    : _node(node), _cached(false), _depth(depth) {  } +FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth) +  : _node(node), _cached(false), _depth(depth) { + +	setPrefix(prefix); +} +  FSDirectory::FSDirectory(const String &name, int depth)    : _node(name), _cached(false), _depth(depth) {  } +FSDirectory::FSDirectory(const String &prefix, const String &name, int depth) +  : _node(name), _cached(false), _depth(depth) { + +	setPrefix(prefix); +} +  FSDirectory::~FSDirectory() {  } +void FSDirectory::setPrefix(const String &prefix) { +	_prefix = prefix; + +	if (!_prefix.empty() && !_prefix.hasSuffix("/")) { +		_prefix += "/"; +	} +} +  FSNode FSDirectory::getFSNode() const {  	return _node;  } @@ -113,7 +133,7 @@ FSNode FSDirectory::lookupCache(NodeCache &cache, const String &name) {  	// make caching as lazy as possible  	if (!name.empty()) {  		if (!_cached) { -			cacheDirectoryRecursive(_node, _depth, ""); +			cacheDirectoryRecursive(_node, _depth, _prefix);  			_cached = true;  		} @@ -157,12 +177,16 @@ SeekableReadStream *FSDirectory::openFile(const String &name) {  }  FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth) { +	return getSubDirectory(String::emptyString, name, depth); +} + +FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth) {  	if (name.empty() || !_node.isDirectory()) {  		return 0;  	}  	FSNode node = lookupCache(_subDirCache, name); -	return new FSDirectory(node, depth); +	return new FSDirectory(prefix, node, depth);  }  void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) { diff --git a/common/archive.h b/common/archive.h index c8d22124fd..ee12196e6f 100644 --- a/common/archive.h +++ b/common/archive.h @@ -36,6 +36,14 @@  namespace Common { +/** + * ArchiveMember is an abstract interface to represent elements inside + * implementations of Archive. + * + * Archive subclasses must provide their own implementation of ArchiveMember, + * and use it when serving calls to listMembers() and listMatchingMembers(). + * Alternatively, the GenericArchiveMember below can be used. + */  class ArchiveMember {  public:  	virtual ~ArchiveMember() { } @@ -48,7 +56,7 @@ typedef List<SharedPtr<ArchiveMember> > ArchiveMemberList;  class Archive;  /** - * Simple ArchiveMemeber implementation which allows + * Simple ArchiveMember implementation which allows   * creation of ArchiveMember compatible objects via   * a simple Archive and name pair.   * @@ -65,11 +73,6 @@ public:  	SeekableReadStream *open();  }; -/** - * FilePtr is a convenient way to keep track of a SeekableReadStream without - * having to worry about releasing its memory. - */ -typedef SharedPtr<SeekableReadStream> FilePtr;  /**   * Archive allows searches of (file)names into an arbitrary container. @@ -116,13 +119,32 @@ typedef SharedPtr<Archive> ArchivePtr;  /**   * FSDirectory models a directory tree from the filesystem and allows users - * to access it through the Archive interface. FSDirectory can represent a - * single directory, or a tree with specified depth, rooted in a 'base' - * directory. - * Searching is case-insensitive, as the main intended goal is supporting - * retrieval of game data. First case-insensitive match is returned when - * searching, thus making FSDirectory heavily dependant on the underlying - * FSNode implementation. + * to access it through the Archive interface. Searching is case-insensitive, + * since the intended goal is supporting retrieval of game data. + * + * FSDirectory can represent a single directory, or a tree with specified depth, + * depending on the value passed to the 'depth' parameter in the constructors. + * Filenames are cached with their relative path, with elements separated by + * backslashes, e.g.: + * + * c:\my\data\file.ext + * + * would be cached as 'data/file.ext' if FSDirectory was created on 'c:/my' with + * depth > 1. If depth was 1, then the 'data' subdirectory would have been + * ignored, instead. + * Again, only BACKSLASHES are used as separators independently from the + * underlying file system. + * + * Relative paths can be specified when calling matching functions like openFile(), + * hasFile(), listMatchingMembers() and listMembers(). Please see the function + * specific comments for more information. + * + * Client code can customize cache by using the constructors with the 'prefix' + * parameter. In this case, the prefix is prepended to each entry in the cache, + * and effectively treated as a 'virtual' parent subdirectory. FSDirectory adds + * a trailing backslash to prefix if needed. Following on with the previous example + * and using 'your' as prefix, the cache entry would have been 'your/data/file.ext'. + *   */  class FSDirectory : public Archive {  	FSNode	_node; @@ -131,6 +153,8 @@ class FSDirectory : public Archive {  	// Key is stored in lowercase.  	typedef HashMap<String, FSNode, IgnoreCase_Hash, IgnoreCase_EqualTo> NodeCache;  	NodeCache	_fileCache, _subDirCache; +	Common::String	_prefix;	// string that is prepended to each cache item key +	void setPrefix(const String &prefix);  	// look for a match  	FSNode lookupCache(NodeCache &cache, const String &name); @@ -143,15 +167,18 @@ class FSDirectory : public Archive {  public:  	/**  	 * Create a FSDirectory representing a tree with the specified depth. Will result in an -	 * unbound FSDirectory if name is not found on the filesystem or is not a directory. +	 * unbound FSDirectory if name is not found on the filesystem or if the node is not a +	 * valid directory.  	 */  	FSDirectory(const String &name, int depth = 1); +	FSDirectory(const FSNode &node, int depth = 1);  	/** -	 * Create a FSDirectory representing a tree with the specified depth. Will result in an -	 * unbound FSDirectory if node does not exist or is not a directory. +	 * Create a FSDirectory representing a tree with the specified depth. The parameter +	 * prefix is prepended to the keys in the cache. See class comment.  	 */ -	FSDirectory(const FSNode &node, int depth = 1); +	FSDirectory(const String &prefix, const String &name, int depth = 1); +	FSDirectory(const String &prefix, const FSNode &node, int depth = 1);  	virtual ~FSDirectory(); @@ -161,14 +188,33 @@ public:  	FSNode getFSNode() const;  	/** -	 * Create a new FSDirectory pointing to a sub directory of the instance. +	 * Create a new FSDirectory pointing to a sub directory of the instance. See class comment +	 * for an explanation of the prefix parameter.  	 * @return a new FSDirectory instance  	 */  	FSDirectory *getSubDirectory(const String &name, int depth = 1); +	FSDirectory *getSubDirectory(const String &prefix, const String &name, int depth = 1); +	/** +	 * Checks for existence in the cache. A full match of relative path and filename is needed +	 * for success. +	 */  	virtual bool hasFile(const String &name); + +	/** +	 * Returns a list of matching file names. Pattern can use GLOB wildcards. +	 */  	virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern); + +	/** +	 * Returns a list of all the files in the cache. +	 */  	virtual int listMembers(ArchiveMemberList &list); + +	/** +	 * Open the specified file. A full match of relative path and filename is needed +	 * for success. +	 */  	virtual SeekableReadStream *openFile(const String &name);  };  | 
