]> git.xonotic.org Git - xonotic/darkplaces.git/blob - filematch.c
buffer up to 32 recent frame numbers for clc_ack to prevent entity
[xonotic/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(const char *in, const char *pattern, int caseinsensitive)
7 {
8         return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false);
9 }
10
11 int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one)
12 {
13         int c1, c2;
14         while (*pattern)
15         {
16                 switch (*pattern)
17                 {
18                 case 0:
19                         return 1; // end of pattern
20                 case '?': // match any single character
21                         if (*in == 0 || strchr(separators, *in))
22                                 return 0; // no match
23                         in++;
24                         pattern++;
25                         break;
26                 case '*': // match anything until following string
27                         if(wildcard_least_one)
28                                 if (*in == 0 || strchr(separators, *in))
29                                         return 0; // no match
30                         if (!*in)
31                                 return 1; // match
32                         pattern++;
33                         while (*in)
34                         {
35                                 if (strchr(separators, *in))
36                                         break;
37                                 // see if pattern matches at this offset
38                                 if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one))
39                                         return 1;
40                                 // nope, advance to next offset
41                                 in++;
42                         }
43                         break;
44                 default:
45                         if (*in != *pattern)
46                         {
47                                 if (!caseinsensitive)
48                                         return 0; // no match
49                                 c1 = *in;
50                                 if (c1 >= 'A' && c1 <= 'Z')
51                                         c1 += 'a' - 'A';
52                                 c2 = *pattern;
53                                 if (c2 >= 'A' && c2 <= 'Z')
54                                         c2 += 'a' - 'A';
55                                 if (c1 != c2)
56                                         return 0; // no match
57                         }
58                         in++;
59                         pattern++;
60                         break;
61                 }
62         }
63         if (*in)
64                 return 0; // reached end of pattern but not end of input
65         return 1; // success
66 }
67
68 // a little strings system
69 void stringlistinit(stringlist_t *list)
70 {
71         memset(list, 0, sizeof(*list));
72 }
73
74 void stringlistfreecontents(stringlist_t *list)
75 {
76         int i;
77         for (i = 0;i < list->numstrings;i++)
78         {
79                 if (list->strings[i])
80                         Z_Free(list->strings[i]);
81                 list->strings[i] = NULL;
82         }
83         list->numstrings = 0;
84         list->maxstrings = 0;
85         if (list->strings)
86                 Z_Free(list->strings);
87         list->strings = NULL;
88 }
89
90 void stringlistappend(stringlist_t *list, const char *text)
91 {
92         size_t textlen;
93         char **oldstrings;
94
95         if (list->numstrings >= list->maxstrings)
96         {
97                 oldstrings = list->strings;
98                 list->maxstrings += 4096;
99                 list->strings = (char **) Z_Malloc(list->maxstrings * sizeof(*list->strings));
100                 if (list->numstrings)
101                         memcpy(list->strings, oldstrings, list->numstrings * sizeof(*list->strings));
102                 if (oldstrings)
103                         Z_Free(oldstrings);
104         }
105         textlen = strlen(text) + 1;
106         list->strings[list->numstrings] = (char *) Z_Malloc(textlen);
107         memcpy(list->strings[list->numstrings], text, textlen);
108         list->numstrings++;
109 }
110
111 void stringlistsort(stringlist_t *list)
112 {
113         int i, j;
114         char *temp;
115         // this is a selection sort (finds the best entry for each slot)
116         for (i = 0;i < list->numstrings - 1;i++)
117         {
118                 for (j = i + 1;j < list->numstrings;j++)
119                 {
120                         if (strcasecmp(list->strings[i], list->strings[j]) > 0)
121                         {
122                                 temp = list->strings[i];
123                                 list->strings[i] = list->strings[j];
124                                 list->strings[j] = temp;
125                         }
126                 }
127         }
128 }
129
130 // operating system specific code
131 static void adddirentry(stringlist_t *list, const char *path, const char *name)
132 {
133         if (strcmp(name, ".") && strcmp(name, ".."))
134         {
135                 char temp[MAX_OSPATH];
136                 dpsnprintf( temp, sizeof( temp ), "%s%s", path, name );
137                 stringlistappend(list, temp);
138         }
139 }
140 #ifdef WIN32
141 #include <windows.h>
142 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
143 {
144         int i;
145         char pattern[4096], *c;
146         WIN32_FIND_DATA n_file;
147         HANDLE hFile;
148         strlcpy (pattern, basepath, sizeof(pattern));
149         strlcat (pattern, path, sizeof (pattern));
150         strlcat (pattern, "*", sizeof (pattern));
151         // ask for the directory listing handle
152         hFile = FindFirstFile(pattern, &n_file);
153         if(hFile == INVALID_HANDLE_VALUE)
154                 return;
155         do {
156                 adddirentry(list, path, n_file.cFileName);
157         } while (FindNextFile(hFile, &n_file) != 0);
158         FindClose(hFile);
159
160         // convert names to lowercase because windows does not care, but pattern matching code often does
161         for (i = 0;i < list->numstrings;i++)
162                 for (c = list->strings[i];*c;c++)
163                         if (*c >= 'A' && *c <= 'Z')
164                                 *c += 'a' - 'A';
165 }
166 #else
167 #include <dirent.h>
168 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
169 {
170         char fullpath[MAX_OSPATH];
171         DIR *dir;
172         struct dirent *ent;
173         dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, *path ? path : "./");
174         dir = opendir(fullpath);
175         if (!dir)
176                 return;
177         while ((ent = readdir(dir)))
178                 adddirentry(list, path, ent->d_name);
179         closedir(dir);
180 }
181 #endif
182