Skip to content

Commit

Permalink
First stab at globbing extension.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Jun 11, 2003
1 parent 4454511 commit 6f3eda6
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 0 deletions.
152 changes: 152 additions & 0 deletions extras/globbing.c
@@ -0,0 +1,152 @@
/** \file globbing.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#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 <pattern> <caseSen>\n"
" where <caseSen> 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 ... */

76 changes: 76 additions & 0 deletions 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 ... */

0 comments on commit 6f3eda6

Please sign in to comment.