Upload 2.0.2
[physicsfs] / extras / globbing.c
1 /** \file globbing.c */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7
8 #include "physfs.h"
9 #include "globbing.h"
10
11 /**
12  * Please see globbing.h for details.
13  *
14  * License: this code is public domain. I make no warranty that it is useful,
15  *  correct, harmless, or environmentally safe.
16  *
17  * This particular file may be used however you like, including copying it
18  *  verbatim into a closed-source project, exploiting it commercially, and
19  *  removing any trace of my name from the source (although I hope you won't
20  *  do that). I welcome enhancements and corrections to this file, but I do
21  *  not require you to send me patches if you make changes. This code has
22  *  NO WARRANTY.
23  *
24  * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
25  *  Please see LICENSE.txt in the root of the source tree.
26  *
27  *  \author Ryan C. Gordon.
28  */
29
30
31 static int matchesPattern(const char *fname, const char *wildcard,
32                           int caseSensitive)
33 {
34     char x, y;
35     const char *fnameptr = fname;
36     const char *wildptr = wildcard;
37
38     while ((*wildptr) && (*fnameptr))
39     {
40         y = *wildptr;
41         if (y == '*')
42         {
43             do
44             {
45                 wildptr++;  /* skip multiple '*' in a row... */
46             } while (*wildptr == '*');
47
48             y = (caseSensitive) ? *wildptr : (char) tolower(*wildptr);
49
50             while (1)
51             {
52                 x = (caseSensitive) ? *fnameptr : (char) tolower(*fnameptr);
53                 if ((!x) || (x == y))
54                     break;
55                 else
56                     fnameptr++;
57             } /* while */
58         } /* if */
59
60         else if (y == '?')
61         {
62             wildptr++;
63             fnameptr++;
64         } /* else if */
65
66         else
67         {
68             if (caseSensitive)
69                 x = *fnameptr;
70             else
71             {
72                 x = tolower(*fnameptr);
73                 y = tolower(y);
74             } /* if */
75
76             wildptr++;
77             fnameptr++;
78
79             if (x != y)
80                 return(0);
81         } /* else */
82     } /* while */
83
84     while (*wildptr == '*')
85         wildptr++;
86
87     return(*fnameptr == *wildptr);
88 } /* matchesPattern */
89
90
91 char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
92                                         int caseSensitive)
93 {
94     char **rc = PHYSFS_enumerateFiles(dir);
95     char **i = rc;
96     char **j;
97
98     while (*i != NULL)
99     {
100         if (matchesPattern(*i, wildcard, caseSensitive))
101             i++;
102         else
103         {
104             /* FIXME: This counts on physfs's allocation method not changing! */
105             free(*i);
106             for (j = i; *j != NULL; j++)
107                 j[0] = j[1];
108         } /* else */
109     } /* for */
110
111     return(rc);
112 } /* PHYSFSEXT_enumerateFilesWildcard */
113
114
115 #ifdef TEST_PHYSFSEXT_ENUMERATEFILESWILDCARD
116 int main(int argc, char **argv)
117 {
118     int rc;
119     char **flist;
120     char **i;
121
122     if (argc != 3)
123     {
124         printf("USAGE: %s <pattern> <caseSen>\n"
125                "   where <caseSen> is 1 or 0.\n", argv[0]);
126         return(1);
127     } /* if */
128
129     if (!PHYSFS_init(argv[0]))
130     {
131         fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError());
132         return(1);
133     } /* if */
134
135     if (!PHYSFS_addToSearchPath(".", 1))
136     {
137         fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError());
138         PHYSFS_deinit();
139         return(1);
140     } /* if */
141
142     flist = PHYSFSEXT_enumerateFilesWildcard("/", argv[1], atoi(argv[2]));
143     rc = 0;
144     for (i = flist; *i; i++)
145     {
146         printf("%s\n", *i);
147         rc++;
148     } /* for */
149     printf("\n  total %d files.\n\n", rc);
150
151     PHYSFS_freeList(flist);
152     PHYSFS_deinit();
153
154     return(0);
155 } /* main */
156 #endif
157
158 /* end of globbing.c ... */
159