Upload 2.0.2
[physicsfs] / extras / globbing.c
diff --git a/extras/globbing.c b/extras/globbing.c
new file mode 100644 (file)
index 0000000..bb83d6a
--- /dev/null
@@ -0,0 +1,159 @@
+/** \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. This code has
+ *  NO WARRANTY.
+ *
+ * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
+ *  Please see LICENSE.txt in the root of the source tree.
+ *
+ *  \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 */
+
+
+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 ... */
+