Improved globbing extra.
Fixed FIXMEs, improved documentation, updated for 2.1 API.
This commit is contained in:
parent
778f1987cf
commit
ec93cca7c7
|
@ -4,8 +4,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
#include "globbing.h"
|
#include "globbing.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
* NO WARRANTY.
|
* NO WARRANTY.
|
||||||
*
|
*
|
||||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||||
* Please see LICENSE.txt in the source's "docs" directory.
|
* Please see the file LICENSE.txt in the source's root directory.
|
||||||
*
|
*
|
||||||
* \author Ryan C. Gordon.
|
* \author Ryan C. Gordon.
|
||||||
*/
|
*/
|
||||||
|
@ -87,28 +87,108 @@ static int matchesPattern(const char *fname, const char *wildcard,
|
||||||
return(*fnameptr == *wildptr);
|
return(*fnameptr == *wildptr);
|
||||||
} /* matchesPattern */
|
} /* matchesPattern */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const PHYSFS_Allocator *allocator;
|
||||||
|
const char *wildcard;
|
||||||
|
int caseSensitive;
|
||||||
|
PHYSFS_EnumFilesCallback callback;
|
||||||
|
void *origData;
|
||||||
|
} WildcardCallbackData;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This callback sits between the enumerator and the enduser callback,
|
||||||
|
* filtering out files that don't match the wildcard pattern.
|
||||||
|
*/
|
||||||
|
static void wildcardCallback(void *_d, const char *origdir, const char *fname)
|
||||||
|
{
|
||||||
|
const WildcardCallbackData *data = (const WildcardCallbackData *) _d;
|
||||||
|
if (matchesPattern(fname, data->wildcard, data->caseSensitive))
|
||||||
|
data->callback(data->origData, origdir, fname);
|
||||||
|
} /* wildcardCallback */
|
||||||
|
|
||||||
|
|
||||||
|
void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||||
|
const char *wildcard,
|
||||||
|
int caseSensitive,
|
||||||
|
PHYSFS_EnumFilesCallback c,
|
||||||
|
void *d)
|
||||||
|
{
|
||||||
|
WildcardCallbackData data;
|
||||||
|
data.allocator = PHYSFS_getAllocator();
|
||||||
|
data.wildcard = wildcard;
|
||||||
|
data.caseSensitive = caseSensitive;
|
||||||
|
data.callback = c;
|
||||||
|
data.origData = d;
|
||||||
|
PHYSFS_enumerateFilesCallback(dir, wildcardCallback, &data);
|
||||||
|
} /* PHYSFSEXT_enumerateFilesCallbackWildcard */
|
||||||
|
|
||||||
|
|
||||||
|
void PHYSFSEXT_freeEnumeration(char **list)
|
||||||
|
{
|
||||||
|
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||||
|
int i;
|
||||||
|
if (list != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; list[i] != NULL; i++)
|
||||||
|
allocator->Free(list[i]);
|
||||||
|
allocator->Free(list);
|
||||||
|
} /* if */
|
||||||
|
} /* PHYSFSEXT_freeEnumeration */
|
||||||
|
|
||||||
|
|
||||||
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
|
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
|
||||||
int caseSensitive)
|
int caseSensitive)
|
||||||
{
|
{
|
||||||
char **rc = PHYSFS_enumerateFiles(dir);
|
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||||
char **i = rc;
|
char **list = PHYSFS_enumerateFiles(dir);
|
||||||
char **j;
|
char **retval = NULL;
|
||||||
|
int totalmatches = 0;
|
||||||
|
int matches = 0;
|
||||||
|
char **i;
|
||||||
|
|
||||||
while (*i != NULL)
|
for (i = list; *i != NULL; i++)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
printf("matchesPattern: '%s' vs '%s' (%s) ... %s\n", *i, wildcard,
|
||||||
|
caseSensitive ? "case" : "nocase",
|
||||||
|
matchesPattern(*i, wildcard, caseSensitive) ? "true" : "false");
|
||||||
|
#endif
|
||||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||||
i++;
|
totalmatches++;
|
||||||
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 */
|
} /* for */
|
||||||
|
|
||||||
return(rc);
|
retval = (char **) allocator->Malloc(sizeof (char *) * (totalmatches+1));
|
||||||
|
if (retval != NULL)
|
||||||
|
{
|
||||||
|
for (i = list; ((matches < totalmatches) && (*i != NULL)); i++)
|
||||||
|
{
|
||||||
|
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||||
|
{
|
||||||
|
retval[matches] = (char *) allocator->Malloc(strlen(*i) + 1);
|
||||||
|
if (retval[matches] == NULL)
|
||||||
|
{
|
||||||
|
while (matches--)
|
||||||
|
allocator->Free(retval[matches]);
|
||||||
|
allocator->Free(retval);
|
||||||
|
retval = NULL;
|
||||||
|
break;
|
||||||
|
} /* if */
|
||||||
|
strcpy(retval[matches], *i);
|
||||||
|
matches++;
|
||||||
|
} /* if */
|
||||||
|
} /* for */
|
||||||
|
|
||||||
|
if (retval != NULL)
|
||||||
|
{
|
||||||
|
assert(totalmatches == matches);
|
||||||
|
retval[matches] = NULL;
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
PHYSFS_freeList(list);
|
||||||
|
return(retval);
|
||||||
} /* PHYSFSEXT_enumerateFilesWildcard */
|
} /* PHYSFSEXT_enumerateFilesWildcard */
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,7 +228,7 @@ int main(int argc, char **argv)
|
||||||
} /* for */
|
} /* for */
|
||||||
printf("\n total %d files.\n\n", rc);
|
printf("\n total %d files.\n\n", rc);
|
||||||
|
|
||||||
PHYSFS_freeList(flist);
|
PHYSFSEXT_freeEnumeration(flist);
|
||||||
PHYSFS_deinit();
|
PHYSFS_deinit();
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/** \file globbing.h */
|
/** \file globbing.h */
|
||||||
|
|
||||||
|
#include "physfs.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \mainpage PhysicsFS globbing
|
* \mainpage PhysicsFS globbing
|
||||||
*
|
*
|
||||||
|
@ -9,10 +11,10 @@
|
||||||
* locating matching entries.
|
* locating matching entries.
|
||||||
*
|
*
|
||||||
* Usage: Set up PhysicsFS as you normally would, then use
|
* Usage: Set up PhysicsFS as you normally would, then use
|
||||||
* PHYSFSEXT_enumerateFilesPattern() when enumerating files. This is just
|
* PHYSFSEXT_enumerateFilesWildcard() when enumerating files. This is just
|
||||||
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
|
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
|
||||||
* wildcard pattern. You must call PHYSFS_freeList() on the results, just
|
* wildcard pattern. You must call PHYSFSEXT_freeEnumeration() on the results,
|
||||||
* like you would with PHYSFS_enumerateFiles().
|
* just PHYSFS_enumerateFiles() would do with PHYSFS_freeList().
|
||||||
*
|
*
|
||||||
* License: this code is public domain. I make no warranty that it is useful,
|
* License: this code is public domain. I make no warranty that it is useful,
|
||||||
* correct, harmless, or environmentally safe.
|
* correct, harmless, or environmentally safe.
|
||||||
|
@ -33,7 +35,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
|
* \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
|
||||||
* \brief Get a file listing of a search path's directory.
|
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern.
|
||||||
*
|
*
|
||||||
* Matching directories are interpolated. That is, if "C:\mydir" is in the
|
* Matching directories are interpolated. That is, if "C:\mydir" is in the
|
||||||
* search path and contains a directory "savegames" that contains "x.sav",
|
* search path and contains a directory "savegames" that contains "x.sav",
|
||||||
|
@ -63,15 +65,89 @@
|
||||||
* Wildcard strings can use the '*' and '?' characters, currently.
|
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
* 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
|
* Don't forget to call PHYSFSEXT_freeEnumerator() with the return value from
|
||||||
* function when you are done with it.
|
* this function when you are done with it. As we use PhysicsFS's allocator
|
||||||
|
* for this list, you must free it before calling PHYSFS_deinit().
|
||||||
|
* Do not use PHYSFS_freeList() on the returned value!
|
||||||
*
|
*
|
||||||
* \param dir directory in platform-independent notation to enumerate.
|
* \param dir directory in platform-independent notation to enumerate.
|
||||||
|
* \param wildcard Wildcard pattern to use for filtering.
|
||||||
|
* \param caseSensitive Zero for case-insensitive matching,
|
||||||
|
* non-zero for case-sensitive.
|
||||||
* \return Null-terminated array of null-terminated strings.
|
* \return Null-terminated array of null-terminated strings.
|
||||||
|
*
|
||||||
|
* \sa PHYSFSEXT_freeEnumeration
|
||||||
*/
|
*/
|
||||||
__EXPORT__ char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
__EXPORT__ char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
||||||
const char *wildcard,
|
const char *wildcard,
|
||||||
int caseSensitive);
|
int caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn void PHYSFSEXT_freeEnumeration(char **list)
|
||||||
|
* \brief Free data returned by PHYSFSEXT_enumerateFilesWildcard
|
||||||
|
*
|
||||||
|
* Conceptually, this works like PHYSFS_freeList(), but is used with data
|
||||||
|
* returned by PHYSFSEXT_enumerateFilesWildcard() only. Be sure to call this
|
||||||
|
* on any returned data from that function before
|
||||||
|
*
|
||||||
|
* \param list Pointer previously returned by
|
||||||
|
* PHYSFSEXT_enumerateFilesWildcard(). It is safe to pass a
|
||||||
|
* NULL here.
|
||||||
|
*
|
||||||
|
* \sa PHYSFSEXT_enumerateFilesWildcard
|
||||||
|
*/
|
||||||
|
__EXPORT__ void PHYSFSEXT_freeEnumeration(char **list);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir, const char *wildcard, int caseSensitive, PHYSFS_EnumFilesCallback c, void *d);
|
||||||
|
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern, using an application-defined callback.
|
||||||
|
*
|
||||||
|
* This function is equivalent to PHYSFSEXT_enumerateFilesWildcard(). It
|
||||||
|
* reports file listings, filtered by a wildcard pattern.
|
||||||
|
*
|
||||||
|
* Unlike PHYSFS_enumerateFiles(), this function does not return an array.
|
||||||
|
* Rather, it calls a function specified by the application once per
|
||||||
|
* element of the search path:
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
*
|
||||||
|
* static void printDir(void *data, const char *origdir, const char *fname)
|
||||||
|
* {
|
||||||
|
* printf(" * We've got [%s] in [%s].\n", fname, origdir);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
* PHYSFS_enumerateFilesCallbackWildcard("savegames","*.sav",0,printDir,NULL);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Items sent to the callback are not guaranteed to be in any order whatsoever.
|
||||||
|
* There is no sorting done at this level, and if you need that, you should
|
||||||
|
* probably use PHYSFS_enumerateFilesWildcard() instead, which guarantees
|
||||||
|
* alphabetical sorting. This form reports whatever is discovered in each
|
||||||
|
* archive before moving on to the next. Even within one archive, we can't
|
||||||
|
* guarantee what order it will discover data. <em>Any sorting you find in
|
||||||
|
* these callbacks is just pure luck. Do not rely on it.</em> As this walks
|
||||||
|
* the entire list of archives, you may receive duplicate filenames.
|
||||||
|
*
|
||||||
|
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||||
|
* Matches can be case-insensitive if you pass a zero for argument 3.
|
||||||
|
*
|
||||||
|
* \param dir Directory, in platform-independent notation, to enumerate.
|
||||||
|
* \param wildcard Wildcard pattern to use for filtering.
|
||||||
|
* \param caseSensitive Zero for case-insensitive matching,
|
||||||
|
* non-zero for case-sensitive.
|
||||||
|
* \param c Callback function to notify about search path elements.
|
||||||
|
* \param d Application-defined data passed to callback. Can be NULL.
|
||||||
|
*
|
||||||
|
* \sa PHYSFS_EnumFilesCallback
|
||||||
|
* \sa PHYSFS_enumerateFiles
|
||||||
|
*/
|
||||||
|
__EXPORT__ void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||||
|
const char *wildcard,
|
||||||
|
int caseSensitive,
|
||||||
|
PHYSFS_EnumFilesCallback c,
|
||||||
|
void *d);
|
||||||
|
|
||||||
/* end of globbing.h ... */
|
/* end of globbing.h ... */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue