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