todo item done: GAME_FNIGGIUM minimum resolution of 640x480
[divverent/darkplaces.git] / filematch.c
1
2 #include "quakedef.h"
3
4 // LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such...
5
6 int matchpattern(char *in, char *pattern, int caseinsensitive)
7 {
8         int c1, c2;
9         while (*pattern)
10         {
11                 switch (*pattern)
12                 {
13                 case '?': // match any single character
14                         if (!*in)
15                                 return 0; // no match
16                         in++;
17                         pattern++;
18                         break;
19                 case '*': // match anything until following string
20                         if (!*in)
21                                 return 1; // match
22                         while (*pattern == '*')
23                                 pattern++;
24                         if (*pattern == '?')
25                         {
26                                 // *? (weird)
27                                 break;
28                         }
29                         else if (*pattern)
30                         {
31                                 // *text (typical)
32                                 while (*in && *in != *pattern)
33                                         in++;
34                         }
35                         else
36                         {
37                                 // *null (* at end of pattern)
38                                 return 1;
39                         }
40                         break;
41                 default:
42                         if (*in != *pattern)
43                         {
44                                 if (!caseinsensitive)
45                                         return 0; // no match
46                                 c1 = *in;
47                                 if (c1 >= 'A' && c1 <= 'Z')
48                                         c1 += 'a' - 'A';
49                                 c2 = *pattern;
50                                 if (c2 >= 'A' && c2 <= 'Z')
51                                         c2 += 'a' - 'A';
52                                 if (c1 != c2)
53                                         return 0; // no match
54                         }
55                         in++;
56                         pattern++;
57                         break;
58                 }
59         }
60         if (*in)
61                 return 0; // reached end of pattern but not end of input
62         return 1; // success
63 }
64
65 // a little chained strings system
66 stringlist_t *stringlistappend(stringlist_t *current, char *text)
67 {
68         stringlist_t *newitem;
69         newitem = Z_Malloc(strlen(text) + 1 + sizeof(stringlist_t));
70         newitem->next = NULL;
71         newitem->text = (char *)(newitem + 1);
72         strcpy(newitem->text, text);
73         if (current)
74                 current->next = newitem;
75         return newitem;
76 }
77
78 void stringlistfree(stringlist_t *current)
79 {
80         stringlist_t *next;
81         while (current)
82         {
83                 next = current->next;
84                 Z_Free(current);
85                 current = next;
86         }
87 }
88
89 stringlist_t *stringlistsort(stringlist_t *start)
90 {
91         int notdone;
92         stringlist_t *current, *previous, *temp2, *temp3, *temp4;
93         notdone = 1;
94         while (notdone)
95         {
96                 current = start;
97                 notdone = 0;
98                 previous = NULL;
99                 while (current && current->next)
100                 {
101                         if (strcmp(current->text, current->next->text) > 0)
102                         {
103                                 // current is greater than next
104                                 notdone = 1;
105                                 temp2 = current->next;
106                                 temp3 = current;
107                                 temp4 = current->next->next;
108                                 if (previous)
109                                         previous->next = temp2;
110                                 else
111                                         start = temp2;
112                                 temp2->next = temp3;
113                                 temp3->next = temp4;
114                                 break;
115                         }
116                         previous = current;
117                         current = current->next;
118                 }
119         }
120         return start;
121 }
122
123 // operating system specific code
124 #ifdef WIN32
125 #include <io.h>
126 stringlist_t *listdirectory(char *path)
127 {
128         char pattern[4096], *c;
129         struct _finddata_t n_file;
130     long hFile;
131         stringlist_t *start, *current;
132         strlcpy (pattern, path, sizeof (pattern));
133         strlcat (pattern, "\\*", sizeof (pattern));
134         // ask for the directory listing handle
135         hFile = _findfirst(pattern, &n_file);
136         if(hFile != -1)
137         {
138                 // start a new chain with the the first name
139                 start = current = stringlistappend(NULL, n_file.name);
140                 // iterate through the directory
141                 while (_findnext(hFile, &n_file) == 0)
142                         current = stringlistappend(current, n_file.name);
143                 _findclose(hFile);
144
145                 // convert names to lowercase because windows does not care, but pattern matching code often does
146                 for (current = start;current;current = current->next)
147                         for (c = current->text;*c;c++)
148                                 if (*c >= 'A' && *c <= 'Z')
149                                         *c += 'a' - 'A';
150
151                 // sort the list alphanumerically
152                 start = stringlistsort(start);
153                 return start;
154         }
155         else
156                 return NULL;
157 }
158 #else
159 #include <dirent.h>
160 stringlist_t *listdirectory(char *path)
161 {
162         DIR *dir;
163         struct dirent *ent;
164         stringlist_t *start, *current;
165         dir = opendir(path);
166         if (!dir)
167                 return NULL;
168         ent = readdir(dir);
169         if (!ent)
170         {
171                 closedir(dir);
172                 return NULL;
173         }
174         start = current = stringlistappend(NULL, ent->d_name);
175         while((ent = readdir(dir)))
176                 current = stringlistappend(current, ent->d_name);
177         closedir(dir);
178         // sort the list alphanumerically
179         return stringlistsort(start);
180 }
181 #endif
182
183 void freedirectory(stringlist_t *list)
184 {
185         stringlistfree(list);
186 }
187