8 #include "darkplaces.h"
14 // LadyHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such...
16 int matchpattern(const char *in, const char *pattern, int caseinsensitive)
18 return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false);
21 // wildcard_least_one: if true * matches 1 or more characters
22 // if false * matches 0 or more characters
23 int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qbool wildcard_least_one)
31 return 1; // end of pattern
32 case '?': // match any single character
33 if (*in == 0 || strchr(separators, *in))
38 case '*': // match anything until following string
39 if(wildcard_least_one)
41 if (*in == 0 || strchr(separators, *in))
48 if (strchr(separators, *in))
50 // see if pattern matches at this offset
51 if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one))
53 // nope, advance to next offset
63 if (c1 >= 'A' && c1 <= 'Z')
66 if (c2 >= 'A' && c2 <= 'Z')
77 return 0; // reached end of pattern but not end of input
81 // a little strings system
82 void stringlistinit(stringlist_t *list)
84 memset(list, 0, sizeof(*list));
87 void stringlistfreecontents(stringlist_t *list)
90 for (i = 0;i < list->numstrings;i++)
93 Z_Free(list->strings[i]);
94 list->strings[i] = NULL;
99 Z_Free(list->strings);
100 list->strings = NULL;
103 void stringlistappend(stringlist_t *list, const char *text)
108 if (list->numstrings >= list->maxstrings)
110 oldstrings = list->strings;
111 list->maxstrings += 4096;
112 list->strings = (char **) Z_Malloc(list->maxstrings * sizeof(*list->strings));
113 if (list->numstrings)
114 memcpy(list->strings, oldstrings, list->numstrings * sizeof(*list->strings));
118 textlen = strlen(text) + 1;
119 list->strings[list->numstrings] = (char *) Z_Malloc(textlen);
120 memcpy(list->strings[list->numstrings], text, textlen);
124 static int stringlistsort_cmp(const void *a, const void *b)
126 return strcasecmp(*(const char **)a, *(const char **)b);
129 void stringlistsort(stringlist_t *list, qbool uniq)
132 if(list->numstrings < 1)
134 qsort(&list->strings[0], list->numstrings, sizeof(list->strings[0]), stringlistsort_cmp);
137 // i: the item to read
138 // j: the item last written
139 for (i = 1, j = 0; i < list->numstrings; ++i)
142 if(!strcasecmp(list->strings[i], list->strings[j]))
145 save = list->strings[j];
146 list->strings[j] = list->strings[i];
147 list->strings[i] = save;
149 for(i = j+1; i < list->numstrings; ++i)
151 if (list->strings[i])
152 Z_Free(list->strings[i]);
154 list->numstrings = j+1;
158 // operating system specific code
159 static void adddirentry(stringlist_t *list, const char *path, const char *name)
161 if (strcmp(name, ".") && strcmp(name, ".."))
163 char temp[MAX_OSPATH];
164 dpsnprintf( temp, sizeof( temp ), "%s%s", path, name );
165 stringlistappend(list, temp);
169 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
172 char pattern[BUFSIZE] = {0};
173 wchar patternw[BUFSIZE] = {0};
174 char filename[BUFSIZE] = {0};
177 WIN32_FIND_DATAW n_file;
179 strlcpy (pattern, basepath, sizeof(pattern));
180 strlcat (pattern, path, sizeof (pattern));
181 strlcat (pattern, "*", sizeof (pattern));
182 fromwtf8(pattern, strlen(pattern), patternw, BUFSIZE);
183 // ask for the directory listing handle
184 hFile = FindFirstFileW(patternw, &n_file);
185 if(hFile == INVALID_HANDLE_VALUE)
188 filenamew = n_file.cFileName;
190 while(filenamew[lenw] != 0) ++lenw;
191 towtf8(filenamew, lenw, filename, BUFSIZE);
192 adddirentry(list, path, filename);
193 } while (FindNextFileW(hFile, &n_file) != 0);
198 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
200 char fullpath[MAX_OSPATH];
203 dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, path);
205 // SDL currently does not support listing assets, so we have to emulate
206 // it. We're using relative paths for assets, so that will do.
207 if (basepath[0] != '/')
209 char listpath[MAX_OSPATH];
211 dpsnprintf(listpath, sizeof(listpath), "%sls.txt", fullpath);
212 char *buf = (char *) FS_SysLoadFile(listpath, tempmempool, true, NULL);
218 char *q = strchr(p, '\n');
222 adddirentry(list, path, p);
229 dir = opendir(fullpath);
233 while ((ent = readdir(dir)))
234 adddirentry(list, path, ent->d_name);