From 6f3eda601e2e3e8244ff0e2c95917f8e20339ae1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Jun 2003 02:10:49 +0000 Subject: [PATCH] First stab at globbing extension. --- extras/globbing.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++ extras/globbing.h | 76 +++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 extras/globbing.c create mode 100644 extras/globbing.h diff --git a/extras/globbing.c b/extras/globbing.c new file mode 100644 index 00000000..a56499f2 --- /dev/null +++ b/extras/globbing.c @@ -0,0 +1,152 @@ +/** \file globbing.c */ + +#include +#include +#include +#include + +#include "physfs.h" +#include "globbing.h" + +/** + * Please see globbing.h for details. + * + * License: this code is public domain. I make no warranty that it is useful, + * correct, harmless, or environmentally safe. + * + * This particular file may be used however you like, including copying it + * verbatim into a closed-source project, exploiting it commercially, and + * removing any trace of my name from the source (although I hope you won't + * do that). I welcome enhancements and corrections to this file, but I do + * not require you to send me patches if you make changes. + * + * Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser + * General Public License: http://www.gnu.org/licenses/lgpl.txt + * + * \author Ryan C. Gordon. + */ + + +static int matchesPattern(const char *fname, const char *wildcard, + int caseSensitive) +{ + char x, y; + const char *fnameptr = fname; + const char *wildptr = wildcard; + + while ((*wildptr) && (*fnameptr)) + { + y = *wildptr; + if (y == '*') + { + wildptr++; + y = (caseSensitive) ? *wildptr : (char) tolower(*wildptr); + + while (1) + { + x = (caseSensitive) ? *fnameptr : (char) tolower(*fnameptr); + if ((!x) || (x == y)) + break; + else + fnameptr++; + } /* while */ + } /* if */ + + else if (y == '?') + { + wildptr++; + fnameptr++; + } /* else if */ + + else + { + if (caseSensitive) + x = *fnameptr; + else + { + x = tolower(*fnameptr); + y = tolower(y); + } /* if */ + + wildptr++; + fnameptr++; + + if (x != y) + return(0); + } /* else */ + + } /* while */ + + return(*fnameptr == *wildptr); +} /* matchesPattern */ + + +char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard, + int caseSensitive) +{ + char **rc = PHYSFS_enumerateFiles(dir); + char **i = rc; + char **j; + + while (*i != NULL) + { + if (matchesPattern(*i, wildcard, caseSensitive)) + i++; + else + { + /* FIXME: This counts on physfs's allocation method not changing! */ + free(*i); + for (j = i; *j != NULL; j++) + j[0] = j[1]; + } /* else */ + } /* for */ + + return(rc); +} /* PHYSFSEXT_enumerateFilesWildcard */ + + +#ifdef TEST_PHYSFSEXT_ENUMERATEFILESWILDCARD +int main(int argc, char **argv) +{ + int rc; + char **flist; + char **i; + + if (argc != 3) + { + printf("USAGE: %s \n" + " where is 1 or 0.\n", argv[0]); + return(1); + } /* if */ + + if (!PHYSFS_init(argv[0])) + { + fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError()); + return(1); + } /* if */ + + if (!PHYSFS_addToSearchPath(".", 1)) + { + fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError()); + PHYSFS_deinit(); + return(1); + } /* if */ + + flist = PHYSFSEXT_enumerateFilesWildcard("/", argv[1], atoi(argv[2])); + rc = 0; + for (i = flist; *i; i++) + { + printf("%s\n", *i); + rc++; + } /* for */ + printf("\n total %d files.\n\n", rc); + + PHYSFS_freeList(flist); + PHYSFS_deinit(); + + return(0); +} /* main */ +#endif + +/* end of globbing.c ... */ + diff --git a/extras/globbing.h b/extras/globbing.h new file mode 100644 index 00000000..96341943 --- /dev/null +++ b/extras/globbing.h @@ -0,0 +1,76 @@ +/** \file globbing.h */ + +/** + * \mainpage PhysicsFS globbing + * + * This is an extension to PhysicsFS to let you search for files with basic + * wildcard matching, regardless of what sort of filesystem or archive they + * reside in. It does this by enumerating directories as needed and manually + * locating matching entries. + * + * Usage: Set up PhysicsFS as you normally would, then use + * PHYSFSEXT_enumerateFilesPattern() when enumerating files. This is just + * like PHYSFS_enumerateFiles(), but it returns a subset that matches your + * wildcard pattern. You must call PHYSFS_freeList() on the results, just + * like you would with PHYSFS_enumerateFiles(). + * + * License: this code is public domain. I make no warranty that it is useful, + * correct, harmless, or environmentally safe. + * + * This particular file may be used however you like, including copying it + * verbatim into a closed-source project, exploiting it commercially, and + * removing any trace of my name from the source (although I hope you won't + * do that). I welcome enhancements and corrections to this file, but I do + * not require you to send me patches if you make changes. + * + * Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser + * General Public License: http://www.gnu.org/licenses/lgpl.txt + * + * \author Ryan C. Gordon. + */ + + +/** + * \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive) + * \brief Get a file listing of a search path's directory. + * + * Matching directories are interpolated. That is, if "C:\mydir" is in the + * search path and contains a directory "savegames" that contains "x.sav", + * "y.Sav", and "z.txt", and there is also a "C:\userdir" in the search path + * that has a "savegames" subdirectory with "w.sav", then the following code: + * + * \code + * char **rc = PHYSFS_enumerateFilesWildcard("savegames", "*.sav", 0); + * char **i; + * + * for (i = rc; *i != NULL; i++) + * printf(" * We've got [%s].\n", *i); + * + * PHYSFS_freeList(rc); + * \endcode + * + * ...will print: + * + * \verbatim + * We've got [x.sav]. + * We've got [y.Sav]. + * We've got [w.sav].\endverbatim + * + * Feel free to sort the list however you like. We only promise there will + * be no duplicates, but not what order the final list will come back in. + * + * Wildcard strings can use the '*' and '?' characters, currently. + * Matches can be case-insensitive if you pass a zero for argument 3. + * + * Don't forget to call PHYSFS_freeList() with the return value from this + * function when you are done with it. + * + * \param dir directory in platform-independent notation to enumerate. + * \return Null-terminated array of null-terminated strings. + */ +__EXPORT__ char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, + const char *wildcard, + int caseSensitive); + +/* end of globbing.h ... */ +