now loads gamedir/*.pak instead of gamedir/pak#.pak, sorted by ASCII value (note...
[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];
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                 // sort the list alphanumerically
133                 return stringlistsort(start);
134         }
135         else
136                 return NULL;
137 }
138 #else
139 #include <dirent.h>
140 stringlist_t *listdirectory(char *path)
141 {
142         DIR *dir;
143         struct dirent *ent;
144         stringlist_t *start, *current;
145         dir = opendir(path);
146         if (!dir)
147                 return NULL;
148         ent = readdir(dir);
149         if (!ent)
150         {
151                 closedir(dir);
152                 return NULL;
153         }
154         start = current = stringlistappend(NULL, ent->d_name);
155         while((ent = readdir(dir)))
156                 current = stringlistappend(current, ent->d_name);
157         closedir(dir);
158         // sort the list alphanumerically
159         return stringlistsort(start);
160 }
161 #endif
162
163 void freedirectory(stringlist_t *list)
164 {
165         stringlistfree(list);
166 }