/** \file globbing.c */ #include #include #include #include #include #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. This code has * NO WARRANTY. * * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license. * Please see the file LICENSE.txt in the source's root directory. * * \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 == '*') { do { wildptr++; /* skip multiple '*' in a row... */ } while (*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 */ while (*wildptr == '*') wildptr++; return (*fnameptr == *wildptr); } /* 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, int caseSensitive) { const PHYSFS_Allocator *allocator = PHYSFS_getAllocator(); char **list = PHYSFS_enumerateFiles(dir); char **retval = NULL; int totalmatches = 0; int matches = 0; char **i; 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)) totalmatches++; } /* for */ 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 */ #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); PHYSFSEXT_freeEnumeration(flist); PHYSFS_deinit(); return 0; } /* main */ #endif /* end of globbing.c ... */