Jump to content
  • Advertisement
Sign in to follow this  
MARS_999

PhysicsFS help needed to read a directories files

This topic is 1622 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am not following how one can use PhysicsFS to parse a directory for it's files and other directories... 

 

e.g. 

I want to parse my games map directory or texture directory how can I do this... I don't see a function to call to read the the directory.

 

Thanks

Share this post


Link to post
Share on other sites
Advertisement

I'm not sure how to do that in PhysFS, but if it helps at all, boost::filesystem does that fairly easily.
 
Here's my own convenience functions that I use:

//Elsewhere: typedef std::vector<std::string> StringList;

enum SubFoldersEnum {IncludeSubFolders, ExcludeSubFolders};

/*
	Returns a list of every file in the folder and (if desired) the files in each sub-folder.
	If 'timeThreshold' is specified, only files that have been written to *after* that threshold are returned.
	If 'fileFilterFunc' is specified, this filters out all file names (not the entire path) that don't pass the filter.
	If 'folderFilterFunc' is specified, entire subdirectories are filtered out.
	If 'pathPrefix' is specified, this determines what prefixes the returned paths.
	Suggestions for 'pathPrefix' are: Nothing ("FolderA"), "./" ("./FolderA") for relative paths, or passing in baseFolder for absolute paths.

	Example:
		"./File1.ext"
		"./File2.ext"
		"./FolderB/File3.ext"
		"./FolderB/File4.ext"
		"./FolderB/Folder2/File5.ext"
		"./File6.ext"
*/
StringList GetFilesInDirectory(const std::string &baseFolder, SubFoldersEnum subFoldersEnum, const std::string &pathPrefix, std::time_t timeThreshold)
{
	//Call the original function, but with filters that accept everything.
	return GetFilesInDirectory(baseFolder, IsAnything, IsAnything, subFoldersEnum, pathPrefix, timeThreshold);
}

StringList GetFilesInDirectory(const std::string &baseFolder, StringValidatorFunc fileFilterFunc, SubFoldersEnum subFoldersEnum, const std::string &pathPrefix, std::time_t timeThreshold)
{
	//Call the original function, but with a directory filter that accepts everything.
	return GetFilesInDirectory(baseFolder, fileFilterFunc, IsAnything, subFoldersEnum, pathPrefix, timeThreshold);
}

StringList GetFilesInDirectory(const std::string &baseFolder, StringValidatorFunc fileFilterFunc, StringValidatorFunc folderFilterFunc,
							   SubFoldersEnum subFoldersEnum, const std::string &pathPrefix, std::time_t timeThreshold)
{
	StringList listOfFiles;
	if(!DirectoryExists(baseFolder))
		return listOfFiles;

	boost::filesystem::directory_iterator directoryIterator(baseFolder);
	boost::filesystem::directory_iterator endOfDirectory; //An unitialized iterator is the end iterator.

	//Loop through everything in this directory.
	for(; directoryIterator != endOfDirectory; directoryIterator++)
	{
		//Make sure the item found is a file and not a folder.
		if(boost::filesystem::is_regular_file(directoryIterator->path()))
		{
			//Get the name of the folder.
			std::string filename = GetFilenameFromPath(directoryIterator->path().generic_string());

			//Check if the filename passes the filter.
			if(fileFilterFunc(filename))
			{
				//Check if it was written to after 'timeThreshold'.
				if(timeThreshold == 0 || timeThreshold < boost::filesystem::last_write_time(directoryIterator->path()))
				{
					//Add it to our list.
					listOfFiles.push_back(ConvertWinPathToUnix(pathPrefix + '/' + filename));
				}
			}
		}
		else if(boost::filesystem::is_directory(directoryIterator->path()))
		{
			//Check to make sure we want to crawl subfolders.
			if(subFoldersEnum == IncludeSubFolders)
			{
				//Get the name of the folder.
				std::string directoryName = GetFinalDirectoryFromPath(directoryIterator->path().generic_string());

				//Check if the directory name passes the filter.
				if(folderFilterFunc(directoryName))
				{
					//Get all subfolders and add them to the list.
					listOfFiles += GetFilesInDirectory(baseFolder + "/" + directoryName, fileFilterFunc, folderFilterFunc, IncludeSubFolders, (pathPrefix + '/' + directoryName + '/'), timeThreshold);
				}
			}
		}
	}

	return listOfFiles;
}

'StringValidatorFunc' is a function pointer (actually, a std::function<bool(const std::string&)>) that can take a string a return either true or false if it accepts the string. I use this for filtering files. Often I pass it my SV_WildcardMatch() functor, to easily filter out something like {"*.jpg", "*.jpeg", "*.png"} - I can also post the code for that, if you desire. It's a slightly modified version of this algorithm.

 

I have a similar function called GetFoldersInDirectory(). It returns folder names instead of file names.

Share this post


Link to post
Share on other sites

There is a function that returns a list you have to free later:

https://icculus.org/physfs/docs/html/physfs_8h.html#a0f4ae950c2dae0735a91263ddd20fbf4

 

There is also a callback version just below that you provide your own data and function to.

 

I am not following this directory path requirements... I put this in and get nothing

 

 
char* path = "C:/Programming/Work/SDL/Debug/";
cmd_enumerate(path);
 

static int cmd_enumerate(char *args)
{
char **rc;
 
if (*args == '\"')
{
args++;
args[strlen(args) - 1] = '\0';
} /* if */
 
rc = PHYSFS_enumerateFiles(args);
 
if (rc == NULL)
printf("Failure. reason: %s.\n", PHYSFS_getLastError());
else
{
int file_count;
char **i;
for (i = rc, file_count = 0; *i != NULL; i++, file_count++)
printf("%s\n", *i);
 
printf("\n total (%d) files.\n", file_count);
PHYSFS_freeList(rc);
} /* else */
 
return(1);
} /* cmd_enumerate */

Share this post


Link to post
Share on other sites

PhysFS is virtual filesystem inspired by id tech ones, so first you mount the directories you want and then you have one, own filesystem that can look at few places or archives as if they are one.

The mounting, search path, write path and platform independent and dependent paths are all explained well on main page:

https://icculus.org/physfs/docs/html/index.html

Edited by FRex

Share this post


Link to post
Share on other sites

I'm not sure how to do that in PhysFS, but if it helps at all, boost::filesystem does that fairly easily.
 
Here's my own convenience functions that I use:

//Elsewhere: typedef std::vector<std::string> StringList;

enum SubFoldersEnum {IncludeSubFolders, ExcludeSubFolders};

/*
	Returns a list of every file in the folder and (if desired) the files in each sub-folder.
	If 'timeThreshold' is specified, only files that have been written to *after* that threshold are returned.
	If 'fileFilterFunc' is specified, this filters out all file names (not the entire path) that don't pass the filter.
	If 'folderFilterFunc' is specified, entire subdirectories are filtered out.
	If 'pathPrefix' is specified, this determines what prefixes the returned paths.
	Suggestions for 'pathPrefix' are: Nothing ("FolderA"), "./" ("./FolderA") for relative paths, or passing in baseFolder for absolute paths.

	Example:
		"./File1.ext"
		"./File2.ext"
		"./FolderB/File3.ext"
		"./FolderB/File4.ext"
		"./FolderB/Folder2/File5.ext"
		"./File6.ext"
*/
StringList GetFilesInDirectory(const std::string &baseFolder, SubFoldersEnum subFoldersEnum, const std::string &pathPrefix, std::time_t timeThreshold)
{
	//Call the original function, but with filters that accept everything.
	return GetFilesInDirectory(baseFolder, IsAnything, IsAnything, subFoldersEnum, pathPrefix, timeThreshold);
}

StringList GetFilesInDirectory(const std::string &baseFolder, StringValidatorFunc fileFilterFunc, SubFoldersEnum subFoldersEnum, const std::string &pathPrefix, std::time_t timeThreshold)
{
	//Call the original function, but with a directory filter that accepts everything.
	return GetFilesInDirectory(baseFolder, fileFilterFunc, IsAnything, subFoldersEnum, pathPrefix, timeThreshold);
}

StringList GetFilesInDirectory(const std::string &baseFolder, StringValidatorFunc fileFilterFunc, StringValidatorFunc folderFilterFunc,
							   SubFoldersEnum subFoldersEnum, const std::string &pathPrefix, std::time_t timeThreshold)
{
	StringList listOfFiles;
	if(!DirectoryExists(baseFolder))
		return listOfFiles;

	boost::filesystem::directory_iterator directoryIterator(baseFolder);
	boost::filesystem::directory_iterator endOfDirectory; //An unitialized iterator is the end iterator.

	//Loop through everything in this directory.
	for(; directoryIterator != endOfDirectory; directoryIterator++)
	{
		//Make sure the item found is a file and not a folder.
		if(boost::filesystem::is_regular_file(directoryIterator->path()))
		{
			//Get the name of the folder.
			std::string filename = GetFilenameFromPath(directoryIterator->path().generic_string());

			//Check if the filename passes the filter.
			if(fileFilterFunc(filename))
			{
				//Check if it was written to after 'timeThreshold'.
				if(timeThreshold == 0 || timeThreshold < boost::filesystem::last_write_time(directoryIterator->path()))
				{
					//Add it to our list.
					listOfFiles.push_back(ConvertWinPathToUnix(pathPrefix + '/' + filename));
				}
			}
		}
		else if(boost::filesystem::is_directory(directoryIterator->path()))
		{
			//Check to make sure we want to crawl subfolders.
			if(subFoldersEnum == IncludeSubFolders)
			{
				//Get the name of the folder.
				std::string directoryName = GetFinalDirectoryFromPath(directoryIterator->path().generic_string());

				//Check if the directory name passes the filter.
				if(folderFilterFunc(directoryName))
				{
					//Get all subfolders and add them to the list.
					listOfFiles += GetFilesInDirectory(baseFolder + "/" + directoryName, fileFilterFunc, folderFilterFunc, IncludeSubFolders, (pathPrefix + '/' + directoryName + '/'), timeThreshold);
				}
			}
		}
	}

	return listOfFiles;
}

'StringValidatorFunc' is a function pointer (actually, a std::function<bool(const std::string&)>) that can take a string a return either true or false if it accepts the string. I use this for filtering files. Often I pass it my SV_WildcardMatch() functor, to easily filter out something like {"*.jpg", "*.jpeg", "*.png"} - I can also post the code for that, if you desire. It's a slightly modified version of this algorithm.

 

I have a similar function called GetFoldersInDirectory(). It returns folder names instead of file names.

yes please post it completely, I have a feeling I am going to need it and have to use boost. I didn't want to but SDL doesn't have anything to read a directories contents...

 

thanks!!!

Share this post


Link to post
Share on other sites

Here's the convenience functions I wrapped around boost.filesystem (sometimes just a renaming of the function wink.png):

FileManagement.cpp | FileManagement.h

 

boost.filesystem has a boost::filepath and boost::directory class that it'd be better to use, but just incase you're interested, here's my hand-rolled functions for std::string.

PathFormatting.cpp | PathFormatting.h

 

CharValidators.cpp | CharValidators.h

StringValidators.cpp | StringValidators.h

WildcardMatch.cpp | WildcardMatch.h

 

Glancing over these files, there are a few areas where they include another header from my codebase, so you'll get some compile errors - but it should be very easy to work around that - they aren't at all badly integrated.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!