File system searches
This page describes how to search through the file system from within your database plugin.
Contents
Motivation
You should be interested in this page if the following is true:
- Your file format should be allowed to open any one of a group of files
- When one file is opened, it should be as if all the files were opened
- You need knowledge of which files are available and which aren't, hence the need for a file system search
- It is not an option to make a "meta-file" that has all of the files listed
- You want to do this in an "approved" way that will be OS-agnostic
Gameplan
The key function is called "ReadAndProcessDirectory". This function takes a callback and the callback is called one time for each file in the directory.
It's arguments are:
- a directory of interest
- a callback
- a void * argument, which will be the "this" pointer for your file format.
Example
Identifying the directory
You will need to extract the directory of interest from the filename for the file that was opened. This filename is fully qualified with its directory.
char slashChar = '/';
#if defined(_WIN32)
slashChar = '\\';
#endif
int last_slash = -1;
while (fileOpened.find(slashChar, last_slash+1) != string::npos)
{
last_slash = fileOpened.find(slashChar, last_slash+1);
}
dir = fileOpened.substr(0, last_slash);
Calling ReadAndProcessDirectory
// At top of file: #include <Utility.h>
ReadAndProcessDirectory(dir, CheckFileCallback, this);
My CheckFileCallback function is called once for each file in the directory. It looks like:
static void
CheckFileCallback(void *args, const std::string &fname, bool isDir,
bool perms, long filesize)
{
avtCEAucdFileFormat *ff = (avtCEAucdFileFormat *) args;
ff->AddFileInThisDirectory(fname);
}
What to do with the files
My "AddFileInThisDirectory" studies the filename to see if the input filename matches the file that was opened in terms of the root.
void
avtCEAucdFileFormat::AddFileInThisDirectory(const std::string &filenameWithDir)
{
char slashChar = '/';
#if defined(_WIN32)
slashChar = '\\';
#endif
int last_slash = -1;
while (filenameWithDir.find(slashChar, last_slash+1) != string::npos)
{
last_slash = filenameWithDir.find(slashChar, last_slash+1);
}
// Filename is filenameWithDir without the directory qualification.
std::string filename = filenameWithDir.substr(last_slash+1);
std::string rootCandidate = "U_" + stem;
if (filename == rootCandidate)
root = filenameWithDir;
else
{
char underscore = '_';
if (filename.find(underscore, 0) == string::npos)
return; // can't be a match.
int start = filename.find(underscore, 0)+1;
int stop = -1;
if (filename.find(underscore, start) == string::npos)
{
std::string extension = ".inp";
if (filename.find(extension, start) == string::npos)
return; // no second underscore, no extension.
stop = filename.find(extension, start);
}
else
stop = filename.find(underscore, start);
std::string file_stem = filename.substr(start, stop-start);
if (file_stem == stem)
domains.push_back(filenameWithDir);
}
}